//===--- Decl.h - Swift Language Declaration ASTs ---------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the Decl class and subclasses.
//
//===----------------------------------------------------------------------===//

#ifndef POLARPHP_AST_DECL_H
#define POLARPHP_AST_DECL_H

#include "polarphp/ast/AccessScope.h"
#include "polarphp/ast/Attr.h"
#include "polarphp/ast/CaptureInfo.h"
#include "polarphp/ast/ClangNode.h"
#include "polarphp/ast/ConcreteDeclRef.h"
#include "polarphp/ast/DefaultArgumentKind.h"
#include "polarphp/ast/DiagnosticConsumer.h"
#include "polarphp/ast/DiagnosticEngine.h"
#include "polarphp/ast/GenericParamKey.h"
#include "polarphp/ast/IfConfigClause.h"
#include "polarphp/ast/LayoutConstraint.h"
#include "polarphp/ast/StorageImpl.h"
#include "polarphp/ast/TypeAlignments.h"
#include "polarphp/ast/TypeWalker.h"
#include "polarphp/ast/Types.h"
#include "polarphp/ast/Witness.h"
#include "polarphp/basic/ArrayRefView.h"
#include "polarphp/basic/Debug.h"
#include "polarphp/basic/InlineBitfield.h"
#include "polarphp/basic/NullablePtr.h"
#include "polarphp/basic/OptionalEnum.h"
#include "polarphp/basic/Range.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/TrailingObjects.h"
#include <type_traits>

namespace polar::llparser {
class Parser;
}

namespace polar {

using polar::count_bits_used;
using polar::bitmax;
using llvm::cast_or_null;
using polar::range;
using polar::OptionalEnum;
using polar::DowncastFilterRange;
using polar::NullablePtr;
using polar::llparser::Parser;

enum class AccessSemantics : unsigned char;
class AccessorDecl;
class ApplyExpr;
class AvailabilityContext;
class GenericEnvironment;
class ArchetypeType;
class AstContext;
struct AstNode;
class AstPrinter;
class AstWalker;
class ConstructorDecl;
class DestructorDecl;
class DiagnosticEngine;
class DynamicSelfType;
class Type;
class Expr;
class DeclRefExpr;
class ForeignErrorConvention;
class LiteralExpr;
class BraceStmt;
class DeclAttributes;
class GenericContext;
class GenericSignature;
class GenericTypeParamDecl;
class GenericTypeParamType;
class ModuleDecl;
class NamedPattern;
class EnumCaseDecl;
class EnumElementDecl;
class ParameterList;
class ParameterTypeFlags;
class Pattern;
struct PrintOptions;
struct PropertyWrapperBackingPropertyInfo;
struct PropertyWrapperTypeInfo;
struct PropertyWrapperMutability;
class InterfaceDecl;
class InterfaceType;
struct RawComment;
enum class ResilienceExpansion : unsigned;
class TypeAliasDecl;
class Stmt;
class SubscriptDecl;
class UnboundGenericType;
class ValueDecl;
class VarDecl;
class OpaqueReturnTypeRepr;

namespace ast_scope {
class AbstractPatternEntryScope;
class PatternEntryDeclScope;
class PatternEntryInitializerScope;
} // namespace ast_scope

enum class DeclKind : uint8_t {
#define DECL(Id, Parent) Id,
#define LAST_DECL(Id) Last_Decl = Id,
#define DECL_RANGE(Id, FirstId, LastId) \
  First_##Id##Decl = FirstId, Last_##Id##Decl = LastId,
#include "polarphp/ast/DeclNodesDef.h"
};
enum : unsigned { NumDeclKindBits =
   count_bits_used(static_cast<unsigned>(DeclKind::Last_Decl)) };


/// Fine-grained declaration kind that provides a description of the
/// kind of entity a declaration represents, as it would be used in
/// diagnostics.
///
/// For example, \c FuncDecl is a single declaration class, but it has
/// several descriptive entries depending on whether it is an
/// operator, global function, local function, method, (observing)
/// accessor, etc.
enum class DescriptiveDeclKind : uint8_t {
   Import,
   Extension,
   EnumCase,
   TopLevelCode,
   IfConfig,
   PoundDiagnostic,
   PatternBinding,
   Var,
   Param,
   Let,
   Property,
   StaticProperty,
   ClassProperty,
   InfixOperator,
   PrefixOperator,
   PostfixOperator,
   PrecedenceGroup,
   TypeAlias,
   GenericTypeParam,
   AssociatedType,
   Type,
   Enum,
   Struct,
   Class,
   Interface,
   GenericEnum,
   GenericStruct,
   GenericClass,
   GenericType,
   Subscript,
   StaticSubscript,
   ClassSubscript,
   Constructor,
   Destructor,
   LocalFunction,
   GlobalFunction,
   OperatorFunction,
   Method,
   StaticMethod,
   ClassMethod,
   Getter,
   Setter,
   Addressor,
   MutableAddressor,
   ReadAccessor,
   ModifyAccessor,
   WillSet,
   DidSet,
   EnumElement,
   Module,
   MissingMember,
   Requirement,
   OpaqueResultType,
   OpaqueVarType
};

/// Describes which spelling was used in the source for the 'static' or 'class'
/// keyword.
enum class StaticSpellingKind : uint8_t {
   None,
   KeywordStatic,
   KeywordClass,
};

/// Keeps track of whether an enum has cases that have associated values.
enum class AssociatedValueCheck {
   /// We have not yet checked.
      Unchecked,
   /// The enum contains no cases or all cases contain no associated values.
      NoAssociatedValues,
   /// The enum contains at least one case with associated values.
      HasAssociatedValues,
};

/// Diagnostic printing of \c StaticSpellingKind.
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, StaticSpellingKind SSK);

/// Encapsulation of the overload signature of a given declaration,
/// which is used to determine uniqueness of a declaration within a
/// given context.
///
/// Two definitions in the same context may not have the same overload
/// signature.
struct OverloadSignature {
   /// The full name of the declaration.
   DeclName Name;

   /// The kind of unary operator.
   UnaryOperatorKind UnaryOperator;

   /// Whether this is an instance member.
   unsigned IsInstanceMember : 1;

   /// Whether this is a variable.
   unsigned IsVariable : 1;

   /// Whether this is a function.
   unsigned IsFunction : 1;

   /// Whether this is a enum element.
   unsigned IsEnumElement : 1;

   /// Whether this is a nominal type.
   unsigned IsNominal : 1;

   /// Whether this is a type alias.
   unsigned IsTypeAlias : 1;

   /// Whether this signature is part of a Interface extension.
   unsigned InInterfaceExtension : 1;

   /// Whether this signature is of a member defined in an extension of a generic
   /// type.
   unsigned InExtensionOfGenericType : 1;

   /// Whether this declaration has an opaque return type.
   unsigned HasOpaqueReturnType : 1;

   OverloadSignature()
      : UnaryOperator(UnaryOperatorKind::None), IsInstanceMember(false),
        IsVariable(false), IsFunction(false), InInterfaceExtension(false),
        InExtensionOfGenericType(false), HasOpaqueReturnType(false) {}
};

/// Determine whether two overload signatures conflict.
///
/// \param sig1 The overload signature of the first declaration.
/// \param sig2 The overload signature of the second declaration.
/// \param skipInterfaceExtensionCheck If \c true, members of Interface extensions
///        will be allowed to conflict with members of Interface declarations.
bool conflicting(const OverloadSignature& sig1, const OverloadSignature& sig2,
                 bool skipInterfaceExtensionCheck = false);

/// Determine whether two overload signatures and overload types conflict.
///
/// \param ctx The AST context.
/// \param sig1 The overload signature of the first declaration.
/// \param sig1Type The overload type of the first declaration.
/// \param sig2 The overload signature of the second declaration.
/// \param sig2Type The overload type of the second declaration.
/// \param wouldConflictInSwift5 If non-null, the referenced boolean will be set
///        to \c true iff the function returns \c false for this version of
///        Swift, but the given overloads will conflict in Swift 5 mode.
/// \param skipInterfaceExtensionCheck If \c true, members of Interface extensions
///        will be allowed to conflict with members of Interface declarations.
bool conflicting(AstContext &ctx,
                 const OverloadSignature& sig1, CanType sig1Type,
                 const OverloadSignature& sig2, CanType sig2Type,
                 bool *wouldConflictInSwift5 = nullptr,
                 bool skipInterfaceExtensionCheck = false);

/// Decl - Base class for all declarations in Swift.
class alignas(1 << DeclAlignInBits) Decl {
protected:
   union { uint64_t OpaqueBits;

      POLAR_INLINE_BITFIELD_BASE(Decl, bitmax(NumDeclKindBits,8)+1+1+1+1+1,
      Kind : bitmax(NumDeclKindBits,8),

      /// Whether this declaration is invalid.
         Invalid : 1,

      /// Whether this declaration was implicitly created, e.g.,
      /// an implicit constructor in a struct.
         Implicit : 1,

      /// Whether this declaration was mapped directly from a Clang AST.
      ///
      /// Use getClangNode() to retrieve the corresponding Clang AST.
         FromClang : 1,

      /// Whether this declaration was added to the surrounding
      /// DeclContext of an active #if config clause.
         EscapedFromIfConfig : 1
      );

      POLAR_INLINE_BITFIELD_FULL(PatternBindingDecl, Decl, 1+2+16,
      /// Whether this pattern binding declares static variables.
      IsStatic : 1,

      /// Whether 'static' or 'class' was used.
         StaticSpelling : 2,

         : NumPadBits,

      /// The number of pattern binding declarations.
         NumPatternEntries : 16
      );

      POLAR_INLINE_BITFIELD_FULL(EnumCaseDecl, Decl, 32,
      : NumPadBits,

      /// The number of tail-allocated element pointers.
      NumElements : 32
      );

      POLAR_INLINE_BITFIELD(ValueDecl, Decl, 1+1+1,
      AlreadyInLookupTable : 1,

      /// Whether we have already checked whether this declaration is a
      /// redeclaration.
         CheckedRedeclaration : 1,

      /// Whether the decl can be accessed by swift users; for instance,
      /// a.storage for lazy var a is a decl that cannot be accessed.
         IsUserAccessible : 1
      );

      POLAR_INLINE_BITFIELD(AbstractStorageDecl, ValueDecl, 1,
      /// Whether this property is a type property (currently unfortunately
      /// called 'static').
      IsStatic : 1
      );

      POLAR_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 1+1+1+1+1+1,
      /// Encodes whether this is a 'let' binding.
      Introducer : 1,

      /// Whether this declaration was an element of a capture list.
         IsCaptureList : 1,

      /// Whether this vardecl has an initial value bound to it in a way
      /// that isn't represented in the AST with an initializer in the pattern
      /// binding.  This happens in cases like "for i in ...", switch cases, etc.
         HasNonPatternBindingInit : 1,

      /// Whether this is a property used in expressions in the debugger.
      /// It is up to the debugger to instruct SIL how to access this variable.
         IsDebuggerVar : 1,

      /// Whether this is the backing storage for a lazy property.
         IsLazyStorageProperty : 1,

      /// Whether this is the backing storage for a property wrapper.
         IsPropertyWrapperBackingProperty : 1
      );

      POLAR_INLINE_BITFIELD(ParamDecl, VarDecl, 1+2+NumDefaultArgumentKindBits,
      /// Whether we've computed the specifier yet.
      SpecifierComputed : 1,

      /// The specifier associated with this parameter.  This determines
      /// the storage semantics of the value e.g. mutability.
         Specifier : 2,

      /// Information about a symbolic default argument, like #file.
         defaultArgumentKind : NumDefaultArgumentKindBits
      );

      POLAR_INLINE_BITFIELD(SubscriptDecl, VarDecl, 2,
      StaticSpelling : 2
      );
      POLAR_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+8+1+1+1+1+1+1,
      /// \see AbstractFunctionDecl::BodyKind
      BodyKind : 3,

      /// Import as member status.
         IAMStatus : 8,

      /// Whether the function has an implicit 'self' parameter.
         HasImplicitSelfDecl : 1,

      /// Whether we are overridden later.
         Overridden : 1,

      /// Whether the function body throws.
         Throws : 1,

      /// Whether this member was synthesized as part of a derived
      /// Interface conformance.
         Synthesized : 1,

      /// Whether this member's body consists of a single expression.
         HasSingleExpressionBody : 1
      );

      POLAR_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl, 1+1+2+1+1+2,
      /// Whether we've computed the 'static' flag yet.
      IsStaticComputed : 1,

      /// Whether this function is a 'static' method.
         IsStatic : 1,

      /// Whether 'static' or 'class' was used.
         StaticSpelling : 2,

      /// Whether we are statically dispatched even if overridable
         ForcedStaticDispatch : 1,

      /// Whether we've computed the 'self' access kind yet.
         SelfAccessComputed : 1,

      /// Backing bits for 'self' access kind.
         SelfAccess : 2
      );

      POLAR_INLINE_BITFIELD(AccessorDecl, FuncDecl, 4+1+1,
      /// The kind of accessor this is.
      AccessorKind : 4,

      /// Whether the accessor is transparent.
         IsTransparent : 1,

      /// Whether we have computed the above.
         IsTransparentComputed : 1
      );

      POLAR_INLINE_BITFIELD(ConstructorDecl, AbstractFunctionDecl, 3+1+1,
      /// The body initialization kind (+1), or zero if not yet computed.
      ///
      /// This value is cached but is not serialized, because it is a property
      /// of the definition of the constructor that is useful only to semantic
      /// analysis and SIL generation.
      ComputedBodyInitKind : 3,

      /// Whether this constructor can fail, by building an Optional type.
         Failable : 1,

      /// Whether this initializer is a stub placed into a subclass to
      /// catch invalid delegations to a designated initializer not
      /// overridden by the subclass. A stub will always trap at runtime.
      ///
      /// Initializer stubs can be invoked from Objective-C or through
      /// the Objective-C runtime; there is no way to directly express
      /// an object construction that will invoke a stub.
         HasStubImplementation : 1
      );

      POLAR_INLINE_BITFIELD_EMPTY(TypeDecl, ValueDecl);
      POLAR_INLINE_BITFIELD_EMPTY(AbstractTypeParamDecl, TypeDecl);

      POLAR_INLINE_BITFIELD_FULL(GenericTypeParamDecl, AbstractTypeParamDecl, 16+16,
      : NumPadBits,

      Depth : 16,
         Index : 16
      );

      POLAR_INLINE_BITFIELD_EMPTY(GenericTypeDecl, TypeDecl);

      POLAR_INLINE_BITFIELD(TypeAliasDecl, GenericTypeDecl, 1+1,
      /// Whether the typealias forwards perfectly to its underlying type.
      IsCompatibilityAlias : 1,
      /// Whether this was a global typealias synthesized by the debugger.
         IsDebuggerAlias : 1
      );

      POLAR_INLINE_BITFIELD(NominalTypeDecl, GenericTypeDecl, 1+1+1,
      /// Whether we have already added implicitly-defined initializers
      /// to this declaration.
      AddedImplicitInitializers : 1,

      /// Whether there is are lazily-loaded conformances for this nominal type.
         HasLazyConformances : 1,

      /// Whether this nominal type is having its semantic members resolved.
         IsComputingSemanticMembers : 1
      );

      POLAR_INLINE_BITFIELD_FULL(InterfaceDecl, NominalTypeDecl, 1+1+1+1+1+1+1+1+1+8+16,
      /// Whether the \c RequiresClass bit is valid.
      RequiresClassValid : 1,

      /// Whether this is a class-bounded Interface.
         RequiresClass : 1,

      /// Whether the \c ExistentialConformsToSelf bit is valid.
         ExistentialConformsToSelfValid : 1,

      /// Whether the existential of this Interface conforms to itself.
         ExistentialConformsToSelf : 1,

      /// Whether the \c ExistentialTypeSupported bit is valid.
         ExistentialTypeSupportedValid : 1,

      /// Whether the existential of this Interface can be represented.
         ExistentialTypeSupported : 1,

      /// True if the Interface has requirements that cannot be satisfied (e.g.
      /// because they could not be imported from Objective-C).
         HasMissingRequirements : 1,

      /// Whether we've computed the inherited Interfaces list yet.
         InheritedInterfacesValid : 1,

      /// Whether we have a lazy-loaded requirement signature.
         HasLazyRequirementSignature : 1,

         : NumPadBits,

      /// If this is a compiler-known Interface, this will be a KnownInterfaceKind
      /// value, plus one. Otherwise, it will be 0.
         KnownInterface : 8, // '8' for speed. This only needs 6.

      /// The number of requirements in the requirement signature.
         NumRequirementsInSignature : 16
      );

      POLAR_INLINE_BITFIELD(ClassDecl, NominalTypeDecl, 1+1+2+1+1+1+1+1+1,
      /// Whether this class inherits its superclass's convenience initializers.
      InheritsSuperclassInits : 1,
         ComputedInheritsSuperclassInits : 1,

      /// \see ClassDecl::ForeignKind
         RawForeignKind : 2,

      /// \see ClassDecl::getEmittedMembers()
         HasForcedEmittedMembers : 1,

         HasMissingDesignatedInitializers : 1,
         ComputedHasMissingDesignatedInitializers : 1,

         HasMissingVTableEntries : 1,
         ComputedHasMissingVTableEntries : 1,

      /// Whether instances of this class are incompatible
      /// with weak and unowned references.
         IsIncompatibleWithWeakReferences : 1
      );

      POLAR_INLINE_BITFIELD(StructDecl, NominalTypeDecl, 1,
      /// True if this struct has storage for fields that aren't accessible in
      /// Swift.
      HasUnreferenceableStorage : 1
      );

      POLAR_INLINE_BITFIELD(EnumDecl, NominalTypeDecl, 2+1,
      /// True if the enum has cases and at least one case has associated values.
      HasAssociatedValues : 2,
      /// True if the enum has at least one case that has some availability
      /// attribute.  A single bit because it's lazily computed along with the
      /// HasAssociatedValues bit.
         HasAnyUnavailableValues : 1
      );

      POLAR_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1,
      /// If the module was or is being compiled with `-enable-testing`.
      TestingEnabled : 1,

      /// If the module failed to load
         FailedToLoad : 1,

      /// Whether the module is resilient.
      ///
      /// \sa ResilienceStrategy
         RawResilienceStrategy : 1,

      /// Whether all imports have been resolved. Used to detect circular imports.
         HasResolvedImports : 1,

      /// If the module was or is being compiled with `-enable-private-imports`.
         PrivateImportsEnabled : 1,

      /// If the module is compiled with `-enable-implicit-dynamic`.
         ImplicitDynamicEnabled : 1,

      /// Whether the module is a system module.
         IsSystemModule : 1,

      /// Whether the module was imported from Clang (or, someday, maybe another
      /// language).
         IsNonSwiftModule : 1
      );

      POLAR_INLINE_BITFIELD(PrecedenceGroupDecl, Decl, 1+2,
      /// Is this an assignment operator?
      IsAssignment : 1,

      /// The group's associativity.  A value of the Associativity enum.
         Associativity : 2
      );

      POLAR_INLINE_BITFIELD(ImportDecl, Decl, 3+8,
      ImportKind : 3,

      /// The number of elements in this path.
         NumPathElements : 8
      );

      POLAR_INLINE_BITFIELD(ExtensionDecl, Decl, 3+1,
      /// An encoding of the default and maximum access level for this extension.
      ///
      /// This is encoded as (1 << (maxAccess-1)) | (1 << (defaultAccess-1)),
      /// which works because the maximum is always greater than or equal to the
      /// default, and 'private' is never used. 0 represents an uncomputed value.
      DefaultAndMaxAccessLevel : 3,

      /// Whether there is are lazily-loaded conformances for this extension.
         HasLazyConformances : 1
      );

      POLAR_INLINE_BITFIELD(IfConfigDecl, Decl, 1,
      /// Whether this decl is missing its closing '#endif'.
      HadMissingEnd : 1
      );

      POLAR_INLINE_BITFIELD(PoundDiagnosticDecl, Decl, 1+1,
      /// `true` if the diagnostic is an error, `false` if it's a warning.
      IsError : 1,

      /// Whether this diagnostic has already been emitted.
         HasBeenEmitted : 1
      );

      POLAR_INLINE_BITFIELD(MissingMemberDecl, Decl, 1+2,
      NumberOfFieldOffsetVectorEntries : 1,
         NumberOfVTableEntries : 2
      );

   } Bits;

   // Storage for the declaration attributes.
   DeclAttributes Attrs;

   /// The next declaration in the list of declarations within this
   /// member context.
   Decl *NextDecl = nullptr;

   friend class DeclIterator;
   friend class IterableDeclContext;
   friend class MemberLookupTable;

private:
   llvm::PointerUnion<DeclContext *, AstContext *> Context;

   Decl(const Decl&) = delete;
   void operator=(const Decl&) = delete;
   SourceLoc getLocFromSource() const;

   struct CachedExternalSourceLocs {
      SourceLoc Loc;
      SourceLoc StartLoc;
      SourceLoc EndLoc;
   };
   mutable CachedExternalSourceLocs const *CachedLocs = nullptr;
   const CachedExternalSourceLocs *calculateSerializedLocs() const;
protected:

   Decl(DeclKind kind, llvm::PointerUnion<DeclContext *, AstContext *> context)
      : Context(context) {
      Bits.OpaqueBits = 0;
      Bits.Decl.Kind = unsigned(kind);
      Bits.Decl.Invalid = false;
      Bits.Decl.Implicit = false;
      Bits.Decl.FromClang = false;
      Bits.Decl.EscapedFromIfConfig = false;
   }

   /// Get the Clang node associated with this declaration.
   ClangNode getClangNodeImpl() const;

   /// Set the Clang node associated with this declaration.
   void setClangNode(ClangNode Node);

   void updateClangNode(ClangNode node) {
      assert(hasClangNode());
      setClangNode(node);
   }
   friend class ClangImporter;

   DeclContext *getDeclContextForModule() const;

public:
   DeclKind getKind() const { return DeclKind(Bits.Decl.Kind); }

   /// Retrieve the name of the given declaration kind.
   ///
   /// This name should only be used for debugging dumps and other
   /// developer aids, and should never be part of a diagnostic or exposed
   /// to the user of the compiler in any way.
   static StringRef getKindName(DeclKind K);

   /// Retrieve the descriptive kind for this declaration.
   DescriptiveDeclKind getDescriptiveKind() const;

   /// Produce a name for the given descriptive declaration kind, which
   /// is suitable for use in diagnostics.
   static StringRef getDescriptiveKindName(DescriptiveDeclKind K);

   /// Whether swift users should be able to access this decl. For instance,
   /// var a.storage for lazy var a is an inaccessible decl. An inaccessible decl
   /// has to be implicit; but an implicit decl does not have to be inaccessible,
   /// for instance, self.
   bool isUserAccessible() const;

   /// Determine if the decl can have a comment.  If false, a comment will
   /// not be serialized.
   bool canHaveComment() const;

   LLVM_READONLY
   DeclContext *getDeclContext() const {
      if (auto dc = Context.dyn_cast<DeclContext *>())
         return dc;

      return getDeclContextForModule();
   }
   void setDeclContext(DeclContext *DC);

   /// Retrieve the innermost declaration context corresponding to this
   /// declaration, which will either be the declaration itself (if it's
   /// also a declaration context) or its declaration context.
   DeclContext *getInnermostDeclContext() const;

   /// Retrieve the module in which this declaration resides.
   LLVM_READONLY
   ModuleDecl *getModuleContext() const;

   /// getAstContext - Return the AstContext that this decl lives in.
   LLVM_READONLY
   AstContext &getAstContext() const {
      if (auto dc = Context.dyn_cast<DeclContext *>())
         return dc->getAstContext();

      return *Context.get<AstContext *>();
   }

   const DeclAttributes &getAttrs() const {
      return Attrs;
   }

   DeclAttributes &getAttrs() {
      return Attrs;
   }

   /// Returns the starting location of the entire declaration.
   SourceLoc getStartLoc() const { return getSourceRange().start; }

   /// Returns the end location of the entire declaration.
   SourceLoc getEndLoc() const { return getSourceRange().end; }

   /// Returns the preferred location when referring to declarations
   /// in diagnostics.
   SourceLoc getLoc(bool SerializedOK = true) const;

   /// Returns the source range of the entire declaration.
   SourceRange getSourceRange() const;

   /// Returns the source range of the declaration including its attributes.
   SourceRange getSourceRangeIncludingAttrs() const;

   SourceLoc TrailingSemiLoc;

   POLAR_DEBUG_DUMP;
   POLAR_DEBUG_DUMPER(dump(const char *filename));
   void dump(raw_ostream &OS, unsigned Indent = 0) const;

   /// Pretty-print the given declaration.
   ///
   /// \param OS Output stream to which the declaration will be printed.
   void print(raw_ostream &OS) const;
   void print(raw_ostream &OS, const PrintOptions &Opts) const;

   /// Pretty-print the given declaration.
   ///
   /// \param Printer AstPrinter object.
   ///
   /// \param Opts Options to control how pretty-printing is performed.
   ///
   /// \returns true if the declaration was printed or false if the print options
   /// required the declaration to be skipped from printing.
   bool print(AstPrinter &Printer, const PrintOptions &Opts) const;

   /// Determine whether this declaration should be printed when
   /// encountered in its declaration context's list of members.
   bool shouldPrintInContext(const PrintOptions &PO) const;

   bool walk(AstWalker &walker);

   /// Return whether this declaration has been determined invalid.
   bool isInvalid() const;

   /// Mark this declaration invalid.
   void setInvalid();

   /// Determine whether this declaration was implicitly generated by the
   /// compiler (rather than explicitly written in source code).
   bool isImplicit() const { return Bits.Decl.Implicit; }

   /// Mark this declaration as implicit.
   void setImplicit(bool implicit = true) { Bits.Decl.Implicit = implicit; }

public:
   bool escapedFromIfConfig() const {
      return Bits.Decl.EscapedFromIfConfig;
   }

   void setEscapedFromIfConfig(bool Escaped) {
      Bits.Decl.EscapedFromIfConfig = Escaped;
   }

   /// \returns the unparsed comment attached to this declaration.
   RawComment getRawComment() const;

   Optional<StringRef> getGroupName() const;

   Optional<StringRef> getSourceFileName() const;

   Optional<unsigned> getSourceOrder() const;

   /// \returns the brief comment attached to this declaration.
   StringRef getBriefComment() const;

   /// Returns true if there is a Clang AST node associated
   /// with self.
   bool hasClangNode() const {
      return Bits.Decl.FromClang;
   }

   /// Retrieve the Clang AST node from which this declaration was
   /// synthesized, if any.
   LLVM_READONLY
   ClangNode getClangNode() const {
      if (!Bits.Decl.FromClang)
         return ClangNode();

      return getClangNodeImpl();
   }

   /// Retrieve the Clang declaration from which this declaration was
   /// synthesized, if any.
   LLVM_READONLY
   const clang::Decl *getClangDecl() const {
      if (!Bits.Decl.FromClang)
         return nullptr;

      return getClangNodeImpl().getAsDecl();
   }

   /// Retrieve the Clang macro from which this declaration was
   /// synthesized, if any.
   LLVM_READONLY
   const clang::MacroInfo *getClangMacro() {
      if (!Bits.Decl.FromClang)
         return nullptr;

      return getClangNodeImpl().getAsMacro();
   }

   /// Return the GenericContext if the Decl has one.
   LLVM_READONLY
   const GenericContext *getAsGenericContext() const;

   bool isPrivateStdlibDecl(bool treatNonBuiltinInterfacesAsPublic = true) const;

   AvailabilityContext getAvailabilityForLinkage() const;

   /// Whether this declaration or one of its outer contexts has the
   /// @_weakLinked attribute.
   bool isAlwaysWeakImported() const;

   /// Whether this declaration is weak-imported from the given module,
   /// either because of the presence of the @_weakLinked attribute, or
   /// because of availability.
   ///
   /// Note that \p fromModule should either be the "main module" or
   /// nullptr. (This is because when it is non-null, we query the
   /// current deployment target, and not the deployment target that
   /// the module was built with.)
   ///
   /// If \p fromModule is the main module, this returns false when the
   /// declaration is part of the main module, or if the declaration is
   /// at least as available as the current deployment target.
   ///
   /// If \p fromModule is null, we instead return true if the
   /// declaration is meant to be weak linked with _some_ deployment
   /// target; that is, the presence of the @_weakLinked attribute or
   /// any kind of availability is enough, irrespective of the current
   /// deployment target.
   bool isWeakImported(ModuleDecl *fromModule) const;

   /// Returns true if the nature of this declaration allows overrides.
   /// Note that this does not consider whether it is final or whether
   /// the class it's on is final.
   ///
   /// If this returns true, the decl can be safely casted to ValueDecl.
   bool isPotentiallyOverridable() const;

   /// If an alternative module name is specified for this decl, e.g. using
   /// @_originalDefinedIn attribute, this function returns this module name.
   StringRef getAlternateModuleName() const;

   /// Emit a diagnostic tied to this declaration.
   template<typename ...ArgTypes>
   InFlightDiagnostic diagnose(
      Diag<ArgTypes...> ID,
      typename detail::PassArgument<ArgTypes>::type... Args) const {
      return getDiags().diagnose(this, ID, std::move(Args)...);
   }

   /// Retrieve the diagnostic engine for diagnostics emission.
   LLVM_READONLY
   DiagnosticEngine &getDiags() const;

   // Make vanilla new/delete illegal for Decls.
   void *operator new(size_t Bytes) = delete;
   void operator delete(void *Data) POLAR_DELETE_OPERATOR_DELETED;

   // Only allow allocation of Decls using the allocator in AstContext
   // or by doing a placement new.
   void *operator new(size_t Bytes, const AstContext &C,
                      unsigned Alignment = alignof(Decl));
   void *operator new(size_t Bytes, void *Mem) {
      assert(Mem);
      return Mem;
   }
};

/// Allocates memory for a Decl with the given \p baseSize. If necessary,
/// it includes additional space immediately preceding the Decl for a ClangNode.
/// \note \p baseSize does not need to include space for a ClangNode if
/// requested -- the necessary space will be added automatically.
template <typename DeclTy, typename AllocatorTy>
void *allocateMemoryForDecl(AllocatorTy &allocator, size_t baseSize,
                            bool includeSpaceForClangNode) {
   static_assert(alignof(DeclTy) >= sizeof(void *),
                 "A pointer must fit in the alignment of the DeclTy!");

   size_t size = baseSize;
   if (includeSpaceForClangNode)
      size += alignof(DeclTy);

   void *mem = allocator.Allocate(size, alignof(DeclTy));
   if (includeSpaceForClangNode)
      mem = reinterpret_cast<char *>(mem) + alignof(DeclTy);
   return mem;
}

enum class RequirementReprKind : unsigned {
   /// A type bound T : P, where T is a type that depends on a generic
   /// parameter and P is some type that should bound T, either as a concrete
   /// supertype or a Interface to which T must conform.
      TypeConstraint,

   /// A same-type requirement T == U, where T and U are types that shall be
   /// equivalent.
      SameType,

   /// A layout bound T : L, where T is a type that depends on a generic
   /// parameter and L is some layout specification that should bound T.
      LayoutConstraint,

   // Note: there is code that packs this enum in a 2-bit bitfield.  Audit users
   // when adding enumerators.
};

/// A single requirement in a 'where' clause, which places additional
/// restrictions on the generic parameters or associated types of a generic
/// function, type, or Interface.
///
/// This always represents a requirement spelled in the source code.  It is
/// never generated implicitly.
///
/// \c GenericParamList assumes these are POD-like.
class RequirementRepr {
   SourceLoc SeparatorLoc;
   RequirementReprKind Kind : 2;
   bool Invalid : 1;
   TypeLoc FirstType;

   /// The second element represents the right-hand side of the constraint.
   /// It can be e.g. a type or a layout constraint.
   union {
      TypeLoc SecondType;
      LayoutConstraintLoc SecondLayout;
   };

   /// Set during deserialization; used to print out the requirements accurately
   /// for the generated interface.
   StringRef AsWrittenString;

   RequirementRepr(SourceLoc SeparatorLoc, RequirementReprKind Kind,
                   TypeLoc FirstType, TypeLoc SecondType)
      : SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
        FirstType(FirstType), SecondType(SecondType) { }

   RequirementRepr(SourceLoc SeparatorLoc, RequirementReprKind Kind,
                   TypeLoc FirstType, LayoutConstraintLoc SecondLayout)
      : SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
        FirstType(FirstType), SecondLayout(SecondLayout) { }

   void printImpl(AstPrinter &OS, bool AsWritten) const;

public:
   /// Construct a new type-constraint requirement.
   ///
   /// \param Subject The type that must conform to the given Interface or
   /// composition, or be a subclass of the given class type.
   /// \param ColonLoc The location of the ':', or an invalid location if
   /// this requirement was implied.
   /// \param Constraint The Interface or Interface composition to which the
   /// subject must conform, or superclass from which the subject must inherit.
   static RequirementRepr getTypeConstraint(TypeLoc Subject,
                                            SourceLoc ColonLoc,
                                            TypeLoc Constraint) {
      return { ColonLoc, RequirementReprKind::TypeConstraint, Subject, Constraint };
   }

   /// Construct a new same-type requirement.
   ///
   /// \param FirstType The first type.
   /// \param EqualLoc The location of the '==' in the same-type constraint, or
   /// an invalid location if this requirement was implied.
   /// \param SecondType The second type.
   static RequirementRepr getSameType(TypeLoc FirstType,
                                      SourceLoc EqualLoc,
                                      TypeLoc SecondType) {
      return { EqualLoc, RequirementReprKind::SameType, FirstType, SecondType };
   }

   /// Construct a new layout-constraint requirement.
   ///
   /// \param Subject The type that must conform to the given layout
   /// requirement.
   /// \param ColonLoc The location of the ':', or an invalid location if
   /// this requirement was implied.
   /// \param Layout The layout requirement to which the
   /// subject must conform.
   static RequirementRepr getLayoutConstraint(TypeLoc Subject,
                                              SourceLoc ColonLoc,
                                              LayoutConstraintLoc Layout) {
      return {ColonLoc, RequirementReprKind::LayoutConstraint, Subject,
              Layout};
   }

   /// Determine the kind of requirement
   RequirementReprKind getKind() const { return Kind; }

   /// Determine whether this requirement is invalid.
   bool isInvalid() const { return Invalid; }

   /// Mark this requirement invalid.
   void setInvalid() { Invalid = true; }

   /// For a type-bound requirement, return the subject of the
   /// conformance relationship.
   Type getSubject() const {
      assert(getKind() == RequirementReprKind::TypeConstraint ||
             getKind() == RequirementReprKind::LayoutConstraint);
      return FirstType.getType();
   }

   TypeRepr *getSubjectRepr() const {
      assert(getKind() == RequirementReprKind::TypeConstraint ||
             getKind() == RequirementReprKind::LayoutConstraint);
      return FirstType.getTypeRepr();
   }

   TypeLoc &getSubjectLoc() {
      assert(getKind() == RequirementReprKind::TypeConstraint ||
             getKind() == RequirementReprKind::LayoutConstraint);
      return FirstType;
   }

   const TypeLoc &getSubjectLoc() const {
      assert(getKind() == RequirementReprKind::TypeConstraint ||
             getKind() == RequirementReprKind::LayoutConstraint);
      return FirstType;
   }

   /// For a type-bound requirement, return the Interface or to which
   /// the subject conforms or superclass it inherits.
   Type getConstraint() const {
      assert(getKind() == RequirementReprKind::TypeConstraint);
      return SecondType.getType();
   }

   TypeRepr *getConstraintRepr() const {
      assert(getKind() == RequirementReprKind::TypeConstraint);
      return SecondType.getTypeRepr();
   }

   TypeLoc &getConstraintLoc() {
      assert(getKind() == RequirementReprKind::TypeConstraint);
      return SecondType;
   }

   const TypeLoc &getConstraintLoc() const {
      assert(getKind() == RequirementReprKind::TypeConstraint);
      return SecondType;
   }

   LayoutConstraint getLayoutConstraint() const {
      assert(getKind() == RequirementReprKind::LayoutConstraint);
      return SecondLayout.getLayoutConstraint();
   }

   LayoutConstraintLoc &getLayoutConstraintLoc() {
      assert(getKind() == RequirementReprKind::LayoutConstraint);
      return SecondLayout;
   }

   const LayoutConstraintLoc &getLayoutConstraintLoc() const {
      assert(getKind() == RequirementReprKind::LayoutConstraint);
      return SecondLayout;
   }

   /// Retrieve the first type of a same-type requirement.
   Type getFirstType() const {
      assert(getKind() == RequirementReprKind::SameType);
      return FirstType.getType();
   }

   TypeRepr *getFirstTypeRepr() const {
      assert(getKind() == RequirementReprKind::SameType);
      return FirstType.getTypeRepr();
   }

   TypeLoc &getFirstTypeLoc() {
      assert(getKind() == RequirementReprKind::SameType);
      return FirstType;
   }

   const TypeLoc &getFirstTypeLoc() const {
      assert(getKind() == RequirementReprKind::SameType);
      return FirstType;
   }

   /// Retrieve the second type of a same-type requirement.
   Type getSecondType() const {
      assert(getKind() == RequirementReprKind::SameType);
      return SecondType.getType();
   }

   TypeRepr *getSecondTypeRepr() const {
      assert(getKind() == RequirementReprKind::SameType);
      return SecondType.getTypeRepr();
   }

   TypeLoc &getSecondTypeLoc() {
      assert(getKind() == RequirementReprKind::SameType);
      return SecondType;
   }

   const TypeLoc &getSecondTypeLoc() const {
      assert(getKind() == RequirementReprKind::SameType);
      return SecondType;
   }

   /// Retrieve the location of the ':' or '==' in an explicitly-written
   /// conformance or same-type requirement respectively.
   SourceLoc getSeparatorLoc() const {
      return SeparatorLoc;
   }

   SourceRange getSourceRange() const {
      if (getKind() == RequirementReprKind::LayoutConstraint)
         return SourceRange(FirstType.getSourceRange().start,
                            SecondLayout.getSourceRange().end);
      return SourceRange(FirstType.getSourceRange().start,
                         SecondType.getSourceRange().end);
   }

   /// Retrieve the first or subject type representation from the \c repr,
   /// or \c nullptr if \c repr is null.
   static TypeRepr *getFirstTypeRepr(const RequirementRepr *repr) {
      if (!repr) return nullptr;
      return repr->FirstType.getTypeRepr();
   }

   /// Retrieve the second or constraint type representation from the \c repr,
   /// or \c nullptr if \c repr is null.
   static TypeRepr *getSecondTypeRepr(const RequirementRepr *repr) {
      if (!repr) return nullptr;
      assert(repr->getKind() == RequirementReprKind::TypeConstraint ||
             repr->getKind() == RequirementReprKind::SameType);
      return repr->SecondType.getTypeRepr();
   }

   POLAR_DEBUG_DUMP;
   void print(raw_ostream &OS) const;
   void print(AstPrinter &Printer) const;
};

/// GenericParamList - A list of generic parameters that is part of a generic
/// function or type, along with extra requirements placed on those generic
/// parameters and types derived from them.
class GenericParamList final :
   private llvm::TrailingObjects<GenericParamList, GenericTypeParamDecl *> {
   friend TrailingObjects;

   SourceRange Brackets;
   unsigned NumParams;
   SourceLoc WhereLoc;
   MutableArrayRef<RequirementRepr> Requirements;

   GenericParamList *OuterParameters;

   SourceLoc TrailingWhereLoc;
   unsigned FirstTrailingWhereArg;

   GenericParamList(SourceLoc LAngleLoc,
                    ArrayRef<GenericTypeParamDecl *> Params,
                    SourceLoc WhereLoc,
                    MutableArrayRef<RequirementRepr> Requirements,
                    SourceLoc RAngleLoc);

   // Don't copy.
   GenericParamList(const GenericParamList &) = delete;
   GenericParamList &operator=(const GenericParamList &) = delete;

public:
   /// create - Create a new generic parameter list within the given AST context.
   ///
   /// \param Context The AstContext in which the generic parameter list will
   /// be allocated.
   /// \param LAngleLoc The location of the opening angle bracket ('<')
   /// \param Params The list of generic parameters, which will be copied into
   /// AstContext-allocated memory.
   /// \param RAngleLoc The location of the closing angle bracket ('>')
   static GenericParamList *create(AstContext &Context,
                                   SourceLoc LAngleLoc,
                                   ArrayRef<GenericTypeParamDecl *> Params,
                                   SourceLoc RAngleLoc);

   /// create - Create a new generic parameter list and "where" clause within
   /// the given AST context.
   ///
   /// \param Context The AstContext in which the generic parameter list will
   /// be allocated.
   /// \param LAngleLoc The location of the opening angle bracket ('<')
   /// \param Params The list of generic parameters, which will be copied into
   /// AstContext-allocated memory.
   /// \param WhereLoc The location of the 'where' keyword, if any.
   /// \param Requirements The list of requirements, which will be copied into
   /// AstContext-allocated memory.
   /// \param RAngleLoc The location of the closing angle bracket ('>')
   static GenericParamList *create(const AstContext &Context,
                                   SourceLoc LAngleLoc,
                                   ArrayRef<GenericTypeParamDecl *> Params,
                                   SourceLoc WhereLoc,
                                   ArrayRef<RequirementRepr> Requirements,
                                   SourceLoc RAngleLoc);

   MutableArrayRef<GenericTypeParamDecl *> getParams() {
      return {getTrailingObjects<GenericTypeParamDecl *>(), NumParams};
   }

   ArrayRef<GenericTypeParamDecl *> getParams() const {
      return {getTrailingObjects<GenericTypeParamDecl *>(), NumParams};
   }

   using iterator = GenericTypeParamDecl **;
   using const_iterator = const GenericTypeParamDecl * const *;

   unsigned size() const { return NumParams; }
   iterator begin() { return getParams().begin(); }
   iterator end() { return getParams().end(); }
   const_iterator begin() const { return getParams().begin(); }
   const_iterator end() const { return getParams().end(); }

   /// Retrieve the location of the 'where' keyword, or an invalid
   /// location if 'where' was not present.
   SourceLoc getWhereLoc() const { return WhereLoc; }

   /// Retrieve the set of additional requirements placed on these
   /// generic parameters and types derived from them.
   ///
   /// This list may contain both explicitly-written requirements as well as
   /// implicitly-generated requirements, and may be non-empty even if no
   /// 'where' keyword is present.
   MutableArrayRef<RequirementRepr> getRequirements() { return Requirements; }

   /// Retrieve the set of additional requirements placed on these
   /// generic parameters and types derived from them.
   ///
   /// This list may contain both explicitly-written requirements as well as
   /// implicitly-generated requirements, and may be non-empty even if no
   /// 'where' keyword is present.
   ArrayRef<RequirementRepr> getRequirements() const { return Requirements; }

   /// Retrieve only those requirements that are written within the brackets,
   /// which does not include any requirements written in a trailing where
   /// clause.
   ArrayRef<RequirementRepr> getNonTrailingRequirements() const {
      return Requirements.slice(0, FirstTrailingWhereArg);
   }

   /// Retrieve only those requirements written in a trailing where
   /// clause.
   ArrayRef<RequirementRepr> getTrailingRequirements() const {
      return Requirements.slice(FirstTrailingWhereArg);
   }

   /// Determine whether the generic parameters have a trailing where clause.
   bool hasTrailingWhereClause() const {
      return FirstTrailingWhereArg < Requirements.size();
   }

   /// Add a trailing 'where' clause to the list of requirements.
   ///
   /// Trailing where clauses are written outside the angle brackets, after the
   /// main part of a declaration's signature.
   void addTrailingWhereClause(AstContext &ctx, SourceLoc trailingWhereLoc,
                               ArrayRef<RequirementRepr> trailingRequirements);

   /// Retrieve the outer generic parameter list.
   ///
   /// This is used for extensions of nested types, and in SIL mode, where a
   /// single lexical context can have multiple logical generic parameter
   /// lists.
   GenericParamList *getOuterParameters() const { return OuterParameters; }

   /// Set the outer generic parameter list. See \c getOuterParameters
   /// for more information.
   void setOuterParameters(GenericParamList *Outer) { OuterParameters = Outer; }

   SourceLoc getLAngleLoc() const { return Brackets.start; }
   SourceLoc getRAngleLoc() const { return Brackets.end; }

   SourceRange getSourceRange() const { return Brackets; }

   /// Retrieve the source range covering the where clause.
   SourceRange getWhereClauseSourceRange() const {
      if (WhereLoc.isInvalid())
         return SourceRange();

      auto endLoc = Requirements[FirstTrailingWhereArg-1].getSourceRange().end;
      return SourceRange(WhereLoc, endLoc);
   }

   /// Retrieve the source range covering the trailing where clause.
   SourceRange getTrailingWhereClauseSourceRange() const {
      if (!hasTrailingWhereClause())
         return SourceRange();

      return SourceRange(TrailingWhereLoc,
                         Requirements.back().getSourceRange().end);
   }

   /// Configure the depth of the generic parameters in this list.
   void setDepth(unsigned depth);

   /// Create a copy of the generic parameter list and all of its generic
   /// parameter declarations. The copied generic parameters are re-parented
   /// to the given DeclContext.
   GenericParamList *clone(DeclContext *dc) const;

   void print(raw_ostream &OS) const;
   POLAR_DEBUG_DUMP;
};

/// A trailing where clause.
class alignas(RequirementRepr) TrailingWhereClause final :
   private llvm::TrailingObjects<TrailingWhereClause, RequirementRepr> {
   friend TrailingObjects;

   SourceLoc WhereLoc;

   /// The number of requirements. The actual requirements are tail-allocated.
   unsigned NumRequirements;

   TrailingWhereClause(SourceLoc whereLoc,
                       ArrayRef<RequirementRepr> requirements);

public:
   /// Create a new trailing where clause with the given set of requirements.
   static TrailingWhereClause *create(AstContext &ctx, SourceLoc whereLoc,
                                      ArrayRef<RequirementRepr> requirements);

   /// Retrieve the location of the 'where' keyword.
   SourceLoc getWhereLoc() const { return WhereLoc; }

   /// Retrieve the set of requirements.
   MutableArrayRef<RequirementRepr> getRequirements() {
      return {getTrailingObjects<RequirementRepr>(), NumRequirements};
   }

   /// Retrieve the set of requirements.
   ArrayRef<RequirementRepr> getRequirements() const {
      return {getTrailingObjects<RequirementRepr>(), NumRequirements};
   }

   /// Compute the source range containing this trailing where clause.
   SourceRange getSourceRange() const {
      return SourceRange(WhereLoc,
                         getRequirements().back().getSourceRange().end);
   }
};

// A private class for forcing exact field layout.
class alignas(8) _GenericContext {
// Not really public. See GenericContext.
public:
   llvm::PointerIntPair<GenericParamList *, 1, bool> GenericParamsAndBit;

   /// The trailing where clause.
   ///
   /// Note that this is not currently serialized, because semantic analysis
   /// moves the trailing where clause into the generic parameter list.
   TrailingWhereClause *TrailingWhere = nullptr;

   /// The generic signature of this declaration.
   llvm::PointerIntPair<GenericSignature, 1, bool> GenericSigAndBit;
};

class GenericContext : private _GenericContext, public DeclContext {
   friend class GenericParamListRequest;
   friend class GenericSignatureRequest;

protected:
   GenericContext(DeclContextKind Kind, DeclContext *Parent,
                  GenericParamList *Params);

public:
   /// Retrieve the set of parameters to a generic context, or null if
   /// this context is not generic.
   GenericParamList *getGenericParams() const;

   /// Determine whether this context has generic parameters
   /// of its own.
   ///
   /// \code
   /// class C<T> {
   ///   func f1() {}    // isGeneric == false
   ///   func f2<T>() {} // isGeneric == true
   /// }
   ///
   /// Interface P { // isGeneric == true due to implicit Self param
   ///   func p()   // isGeneric == false
   /// }
   /// \endcode
   bool isGeneric() const { return getGenericParams() != nullptr; }
   bool hasComputedGenericSignature() const;
   bool isComputingGenericSignature() const;

   /// Retrieve the trailing where clause for this extension, if any.
   TrailingWhereClause *getTrailingWhereClause() const {
      return TrailingWhere;
   }

   /// Set the trailing where clause for this extension.
   void setTrailingWhereClause(TrailingWhereClause *trailingWhereClause) {
      TrailingWhere = trailingWhereClause;
   }

   /// Retrieve the generic signature for this context.
   GenericSignature getGenericSignature() const;

   /// Retrieve the generic context for this context.
   GenericEnvironment *getGenericEnvironment() const;

   /// Retrieve the innermost generic parameter types.
   TypeArrayView<GenericTypeParamType> getInnermostGenericParamTypes() const;

   /// Retrieve the generic requirements.
   ArrayRef<Requirement> getGenericRequirements() const;

   /// Set the generic signature of this context.
   void setGenericSignature(GenericSignature genericSig);

   /// Retrieve the position of any where clause for this context's
   /// generic parameters.
   SourceRange getGenericTrailingWhereClauseSourceRange() const;
};
static_assert(sizeof(_GenericContext) + sizeof(DeclContext) ==
              sizeof(GenericContext), "Please add fields to _GenericContext");

/// Describes what kind of name is being imported.
///
/// If the enumerators here are changed, make sure to update all diagnostics
/// using ImportKind as a select index.
enum class ImportKind : uint8_t {
   Module = 0,
   Type,
   Struct,
   Class,
   Enum,
   Interface,
   Var,
   Func
};

/// ImportDecl - This represents a single import declaration, e.g.:
///   import Swift
///   import typealias Swift.Int
class ImportDecl final : public Decl,
                         private llvm::TrailingObjects<ImportDecl, std::pair<Identifier,SourceLoc>> {
   friend TrailingObjects;
   friend class Decl;
public:
   typedef std::pair<Identifier, SourceLoc> AccessPathElement;

private:
   SourceLoc ImportLoc;
   SourceLoc KindLoc;

   /// The resolved module.
   ModuleDecl *Mod = nullptr;
   /// The resolved decls if this is a decl import.
   ArrayRef<ValueDecl *> Decls;

   ImportDecl(DeclContext *DC, SourceLoc ImportLoc, ImportKind K,
              SourceLoc KindLoc, ArrayRef<AccessPathElement> Path);

public:
   static ImportDecl *create(AstContext &C, DeclContext *DC,
                             SourceLoc ImportLoc, ImportKind Kind,
                             SourceLoc KindLoc,
                             ArrayRef<AccessPathElement> Path,
                             ClangNode ClangN = ClangNode());

   /// Returns the import kind that is most appropriate for \p VD.
   ///
   /// Note that this will never return \c Type; an imported typealias will use
   /// the more specific kind from its underlying type.
   static ImportKind getBestImportKind(const ValueDecl *VD);

   /// Returns the most appropriate import kind for the given list of decls.
   ///
   /// If the list is non-homogeneous, or if there is more than one decl that
   /// cannot be overloaded, returns None.
   static Optional<ImportKind> findBestImportKind(ArrayRef<ValueDecl *> Decls);

   ArrayRef<AccessPathElement> getFullAccessPath() const {
      return {getTrailingObjects<AccessPathElement>(),
              static_cast<size_t>(Bits.ImportDecl.NumPathElements)};
   }

   ArrayRef<AccessPathElement> getModulePath() const {
      auto result = getFullAccessPath();
      if (getImportKind() != ImportKind::Module)
         result = result.slice(0, result.size()-1);
      return result;
   }

   ArrayRef<AccessPathElement> getDeclPath() const {
      if (getImportKind() == ImportKind::Module)
         return {};
      return getFullAccessPath().back();
   }

   ImportKind getImportKind() const {
      return static_cast<ImportKind>(Bits.ImportDecl.ImportKind);
   }

   bool isExported() const {
      return getAttrs().hasAttribute<ExportedAttr>();
   }

   ModuleDecl *getModule() const { return Mod; }
   void setModule(ModuleDecl *M) { Mod = M; }

   ArrayRef<ValueDecl *> getDecls() const { return Decls; }
   void setDecls(ArrayRef<ValueDecl *> Ds) { Decls = Ds; }

   const clang::Module *getClangModule() const {
      return getClangNode().getClangModule();
   }

   SourceLoc getStartLoc() const { return ImportLoc; }
   SourceLoc getLocFromSource() const { return getFullAccessPath().front().second; }
   SourceRange getSourceRange() const {
      return SourceRange(ImportLoc, getFullAccessPath().back().second);
   }
   SourceLoc getKindLoc() const { return KindLoc; }

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Import;
   }
};

/// ExtensionDecl - This represents a type extension containing methods
/// associated with the type.  This is not a ValueDecl and has no Type because
/// there are no runtime values of the Extension's type.
class ExtensionDecl final : public GenericContext, public Decl,
                            public IterableDeclContext {
   SourceLoc ExtensionLoc;  // Location of 'extension' keyword.
   SourceRange Braces;

   /// The type being extended.
   TypeRepr *ExtendedTypeRepr;

   /// The nominal type being extended.
   ///
   /// The bit indicates whether binding has been attempted. The pointer can be
   /// null if either no binding was attempted or if binding could not find  the
   /// extended nominal.
   llvm::PointerIntPair<NominalTypeDecl *, 1, bool> ExtendedNominal;

   MutableArrayRef<TypeLoc> Inherited;

   /// The next extension in the linked list of extensions.
   ///
   /// The bit indicates whether this extension has been resolved to refer to
   /// a known nominal type.
   llvm::PointerIntPair<ExtensionDecl *, 1, bool> NextExtension
      = {nullptr, false};

   /// Note that we have added a member into the iterable declaration context.
   void addedMember(Decl *member);

   friend class ExtensionIterator;
   friend class NominalTypeDecl;
   friend class MemberLookupTable;
   friend class ConformanceLookupTable;
   friend class IterableDeclContext;

   ExtensionDecl(SourceLoc extensionLoc, TypeRepr *extendedType,
                 MutableArrayRef<TypeLoc> inherited,
                 DeclContext *parent,
                 TrailingWhereClause *trailingWhereClause);

   /// Retrieve the conformance loader (if any), and removing it in the
   /// same operation. The caller is responsible for loading the
   /// conformances.
   std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoader() {
      if (!Bits.ExtensionDecl.HasLazyConformances)
         return { nullptr, 0 };

      return takeConformanceLoaderSlow();
   }

   /// Slow path for \c takeConformanceLoader().
   std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoaderSlow();

   friend class ExtendedNominalRequest;
   friend class Decl;
public:
   using Decl::getAstContext;

   /// Create a new extension declaration.
   static ExtensionDecl *create(AstContext &ctx, SourceLoc extensionLoc,
                                TypeRepr *extendedType,
                                MutableArrayRef<TypeLoc> inherited,
                                DeclContext *parent,
                                TrailingWhereClause *trailingWhereClause,
                                ClangNode clangNode = ClangNode());

   SourceLoc getStartLoc() const { return ExtensionLoc; }
   SourceLoc getLocFromSource() const { return ExtensionLoc; }
   SourceRange getSourceRange() const {
      return { ExtensionLoc, Braces.end };
   }

   SourceRange getBraces() const { return Braces; }
   void setBraces(SourceRange braces) { Braces = braces; }

   bool hasBeenBound() const { return ExtendedNominal.getInt(); }

   void setExtendedNominal(NominalTypeDecl *n) {
      ExtendedNominal.setPointerAndInt(n, true);
   }

   /// Retrieve the type being extended.
   ///
   /// Only use this entry point when the complete type, as spelled in the source,
   /// is required. For most clients, \c getExtendedNominal(), which provides
   /// only the \c NominalTypeDecl, will suffice.
   Type getExtendedType() const;

   /// Retrieve the nominal type declaration that is being extended.
   /// Will  trip an assertion if the declaration has not already been computed.
   /// In order to fail fast when type checking work is attempted
   /// before extension binding has taken place.

   NominalTypeDecl *getExtendedNominal() const;

   /// Compute the nominal type declaration that is being extended.
   NominalTypeDecl *computeExtendedNominal() const;

   /// \c hasBeenBound means nothing if this extension can never been bound
   /// because it is not at the top level.
   bool canNeverBeBound() const;

   bool hasValidParent() const;

   /// Determine whether this extension has already been bound to a nominal
   /// type declaration.
   bool alreadyBoundToNominal() const { return NextExtension.getInt(); }

   /// Retrieve the extended type definition as written in the source, if it exists.
   TypeRepr *getExtendedTypeRepr() const { return ExtendedTypeRepr; }

   /// Retrieve the set of Interfaces that this type inherits (i.e,
   /// explicitly conforms to).
   MutableArrayRef<TypeLoc> getInherited() { return Inherited; }
   ArrayRef<TypeLoc> getInherited() const { return Inherited; }

   void setInherited(MutableArrayRef<TypeLoc> i) { Inherited = i; }

   bool hasDefaultAccessLevel() const {
      return Bits.ExtensionDecl.DefaultAndMaxAccessLevel != 0;
   }

   uint8_t getDefaultAndMaxAccessLevelBits() const {
      return Bits.ExtensionDecl.DefaultAndMaxAccessLevel;
   }
   void setDefaultAndMaxAccessLevelBits(AccessLevel defaultAccess,
                                        AccessLevel maxAccess) {
      Bits.ExtensionDecl.DefaultAndMaxAccessLevel =
         (1 << (static_cast<unsigned>(defaultAccess) - 1)) |
         (1 << (static_cast<unsigned>(maxAccess) - 1));
   }

   AccessLevel getDefaultAccessLevel() const;
   AccessLevel getMaxAccessLevel() const;

   void setDefaultAndMaxAccess(AccessLevel defaultAccess,
                               AccessLevel maxAccess) {
      assert(!hasDefaultAccessLevel() && "default access level already set");
      assert(maxAccess >= defaultAccess);
      assert(maxAccess != AccessLevel::Private && "private not valid");
      assert(defaultAccess != AccessLevel::Private && "private not valid");
      setDefaultAndMaxAccessLevelBits(defaultAccess, maxAccess);
      assert(getDefaultAccessLevel() == defaultAccess && "not enough bits");
      assert(getMaxAccessLevel() == maxAccess && "not enough bits");
   }

   void setConformanceLoader(LazyMemberLoader *resolver, uint64_t contextData);

   /// Determine whether this is a constrained extension, which adds additional
   /// requirements beyond those of the nominal type.
   bool isConstrainedExtension() const;

   /// Determine whether this extension context is interchangeable with the
   /// original nominal type context.
   ///
   /// False if any of the following properties hold:
   /// - the extension is defined in a different module from the original
   ///   nominal type decl,
   /// - the extension is constrained, or
   /// - the extension is to a Interface.
   /// FIXME: In a world where Interface extensions are dynamically dispatched,
   /// "extension is to a Interface" would no longer be a reason to use the
   /// extension mangling, because an extension method implementation could be
   /// resiliently moved into the original Interface itself.
   bool isEquivalentToExtendedContext() const;

   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Extension;
   }
   static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDecl())
         return classof(D);
      return false;
   }
   static bool classof(const IterableDeclContext *C) {
      return C->getIterableContextKind()
             == IterableDeclContextKind::ExtensionDecl;
   }

   using DeclContext::operator new;
};

/// Iterator that walks the extensions of a particular type.
class ExtensionIterator {
   ExtensionDecl *current;

public:
   ExtensionIterator() : current() { }
   explicit ExtensionIterator(ExtensionDecl *current) : current(current) { }

   ExtensionDecl *operator*() const { return current; }
   ExtensionDecl *operator->() const { return current; }

   ExtensionIterator &operator++() {
      current = current->NextExtension.getPointer();
      return *this;
   }

   ExtensionIterator operator++(int) {
      ExtensionIterator tmp = *this;
      ++(*this);
      return tmp;
   }

   friend bool operator==(ExtensionIterator x, ExtensionIterator y) {
      return x.current == y.current;
   }

   friend bool operator!=(ExtensionIterator x, ExtensionIterator y) {
      return x.current != y.current;
   }
};

/// Range that covers a set of extensions.
class ExtensionRange {
   ExtensionIterator first;
   ExtensionIterator last;

public:

   ExtensionRange(ExtensionIterator first, ExtensionIterator last)
      : first(first), last(last) { }

   typedef ExtensionIterator iterator;
   iterator begin() const { return first; }
   iterator end() const { return last; }
};


/// This represents one entry in a PatternBindingDecl, which are pairs of
/// Pattern and Initialization expression.  The pattern is always present, but
/// the initializer can be null if there is none.
class PatternBindingEntry {
   enum class Flags {
      Checked = 1 << 0,
      Removed = 1 << 1,
      /// Whether the contents of this initializer were subsumed by
      /// some other initialization, e.g., a lazy property's initializer
      /// gets subsumed by the getter body.
         Subsumed = 1 << 2,
   };
   llvm::PointerIntPair<Pattern *, 3, OptionSet<Flags>> PatternAndFlags;

   struct InitializerAndEqualLoc {
      // When the initializer is removed we don't actually clear the pointers
      // because we might need to get initializer's source range. Since the
      // initializer is AstContext-allocated it is safe.

      /// Exactly the expr the programmer wrote
      Expr *originalInit;
      /// Might be transformed, e.g. for a property wrapper. In the absence of
      /// transformation or synthesis, holds the expr as parsed.
      Expr *initAfterSynthesis;
      /// The location of the equal '=' token.
      SourceLoc EqualLoc;
   };

   union {
      /// The initializer expression and its '=' token loc.
      InitializerAndEqualLoc InitExpr;

      /// The text of the initializer expression if deserialized from a module.
      StringRef InitStringRepresentation;
   };

   enum class PatternFlags {
      IsText = 1 << 0,
      IsFullyValidated = 1 << 1,
   };
   /// The initializer context used for this pattern binding entry.
   llvm::PointerIntPair<DeclContext *, 2, OptionSet<PatternFlags>>
      InitContextAndFlags;

   /// Values captured by this initializer.
   CaptureInfo Captures;

   friend class Parser;
   friend class PatternBindingInitializer;
   friend class PatternBindingDecl;
   friend class ast_scope::AbstractPatternEntryScope;
   friend class ast_scope::PatternEntryDeclScope;
   friend class ast_scope::PatternEntryInitializerScope;

private:
   // FIXME: This API is transitional. Once the callers of
   // typeCheckPatternBinding are requestified, merge this bit with
   // Flags::Checked.
   friend class PatternBindingEntryRequest;

   bool isFullyValidated() const {
      return InitContextAndFlags.getInt().contains(
         PatternFlags::IsFullyValidated);
   }
   void setFullyValidated() {
      InitContextAndFlags.setInt(InitContextAndFlags.getInt() |
                                 PatternFlags::IsFullyValidated);
   }

public:
   /// \p E is the initializer as parsed.
   PatternBindingEntry(Pattern *P, SourceLoc EqualLoc, Expr *E,
                       DeclContext *InitContext)
      : PatternAndFlags(P, {}), InitExpr({E, E, EqualLoc}),
        InitContextAndFlags({InitContext, None}) {}

private:
   Pattern *getPattern() const { return PatternAndFlags.getPointer(); }
   void setPattern(Pattern *P) { PatternAndFlags.setPointer(P); }

   /// Whether the given pattern binding entry is initialized.
   ///
   /// \param onlyExplicit Only consider explicit initializations (rather
   /// than implicitly-generated ones).
   bool isInitialized(bool onlyExplicit = false) const;

   Expr *getInit() const {
      if (PatternAndFlags.getInt().contains(Flags::Removed) ||
          InitContextAndFlags.getInt().contains(PatternFlags::IsText))
         return nullptr;
      return InitExpr.initAfterSynthesis;
   }
   /// Retrieve the initializer if it should be executed to initialize this
   /// particular pattern binding.
   Expr *getExecutableInit() const {
      return isInitializerSubsumed() ? nullptr : getInit();
   }
   SourceRange getOriginalInitRange() const;
   void setInit(Expr *E);

   /// Gets the text of the initializer expression, stripping out inactive
   /// branches of any #ifs inside the expression.
   StringRef getInitStringRepresentation(SmallVectorImpl<char> &scratch) const;

   /// Sets the initializer string representation to the string that was
   /// deserialized from a partial module.
   void setInitStringRepresentation(StringRef str) {
      InitStringRepresentation = str;
      InitContextAndFlags.setInt(InitContextAndFlags.getInt() |
                                 PatternFlags::IsText);
   }

   /// Whether this pattern entry can generate a string representation of its
   /// initializer expression.
   bool hasInitStringRepresentation() const;

   /// Retrieve the location of the equal '=' token.
   SourceLoc getEqualLoc() const {
      return InitContextAndFlags.getInt().contains(PatternFlags::IsText)
             ? SourceLoc()
             : InitExpr.EqualLoc;
   }

   /// Set the location of the equal '=' token.
   void setEqualLoc(SourceLoc equalLoc) {
      assert(!InitContextAndFlags.getInt().contains(PatternFlags::IsText) &&
             "cannot set equal loc for textual initializer");
      InitExpr.EqualLoc = equalLoc;
   }

   /// Retrieve the initializer after the =, if any, as it was written in the
   /// source.
   Expr *getOriginalInit() const;

   /// Set the initializer after the = as it was written in the source.
   void setOriginalInit(Expr *);

   bool isInitializerChecked() const {
      return PatternAndFlags.getInt().contains(Flags::Checked);
   }
   void setInitializerChecked() {
      PatternAndFlags.setInt(PatternAndFlags.getInt() | Flags::Checked);
   }

   bool isInitializerSubsumed() const {
      return PatternAndFlags.getInt().contains(Flags::Subsumed);
   }
   void setInitializerSubsumed() {
      PatternAndFlags.setInt(PatternAndFlags.getInt() | Flags::Subsumed);
   }

   // Return the first variable initialized by this pattern.
   VarDecl *getAnchoringVarDecl() const;

   // Retrieve the declaration context for the initializer.
   DeclContext *getInitContext() const {
      return InitContextAndFlags.getPointer();
   }

   /// Override the initializer context.
   void setInitContext(DeclContext *dc) { InitContextAndFlags.setPointer(dc); }

   SourceLoc getStartLoc() const;

   /// Retrieve the end location covered by this pattern binding entry.
   ///
   /// \param omitAccessors Whether the computation should omit the accessors
   /// from the source range.
   SourceLoc getEndLoc(bool omitAccessors = false) const;

   /// Retrieve the source range covered by this pattern binding entry.
   ///
   /// \param omitAccessors Whether the computation should omit the accessors
   /// from the source range.
   SourceRange getSourceRange(bool omitAccessors = false) const;

   CaptureInfo getCaptureInfo() const { return Captures; }
   void setCaptureInfo(CaptureInfo captures) { Captures = captures; }

   unsigned getNumBoundVariables() const;

private:
   SourceLoc getLastAccessorEndLoc() const;
};

/// This decl contains a pattern and optional initializer for a set
/// of one or more VarDecls declared together.
///
/// For example, in
/// \code
///   var (a, b) = foo(), (c,d) = bar()
/// \endcode
///
/// this includes two entries in the pattern list.  The first contains the
/// pattern "(a, b)" and the initializer "foo()".  The second contains the
/// pattern "(c, d)" and the initializer "bar()".
///
class PatternBindingDecl final : public Decl,
                                 private llvm::TrailingObjects<PatternBindingDecl, PatternBindingEntry> {
   friend TrailingObjects;
   friend class Decl;
   friend class PatternBindingEntryRequest;

   SourceLoc StaticLoc; ///< Location of the 'static/class' keyword, if present.
   SourceLoc VarLoc;    ///< Location of the 'var' keyword.

   friend class Decl;

   PatternBindingDecl(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
                      SourceLoc VarLoc, unsigned NumPatternEntries,
                      DeclContext *Parent);
   SourceLoc getLocFromSource() const { return VarLoc; }
public:
   static PatternBindingDecl *create(AstContext &Ctx, SourceLoc StaticLoc,
                                     StaticSpellingKind StaticSpelling,
                                     SourceLoc VarLoc,
                                     ArrayRef<PatternBindingEntry> PatternList,
                                     DeclContext *Parent);

   static PatternBindingDecl *create(AstContext &Ctx, SourceLoc StaticLoc,
                                     StaticSpellingKind StaticSpelling,
                                     SourceLoc VarLoc, Pattern *Pat,
                                     SourceLoc EqualLoc, Expr *E,
                                     DeclContext *Parent);

   static PatternBindingDecl *createImplicit(AstContext &Ctx,
                                             StaticSpellingKind StaticSpelling,
                                             Pattern *Pat, Expr *E,
                                             DeclContext *Parent,
                                             SourceLoc VarLoc = SourceLoc());

   static PatternBindingDecl *createDeserialized(
      AstContext &Ctx, SourceLoc StaticLoc,
      StaticSpellingKind StaticSpelling,
      SourceLoc VarLoc,
      unsigned NumPatternEntries,
      DeclContext *Parent);

   SourceLoc getStartLoc() const {
      return StaticLoc.isValid() ? StaticLoc : VarLoc;
   }
   SourceRange getSourceRange() const;

   unsigned getNumPatternEntries() const {
      return Bits.PatternBindingDecl.NumPatternEntries;
   }

   ArrayRef<PatternBindingEntry> getPatternList() const {
      return const_cast<PatternBindingDecl*>(this)->getMutablePatternList();
   }

   void setInitStringRepresentation(unsigned i, StringRef str) {
      getMutablePatternList()[i].setInitStringRepresentation(str);
   }

   /// Whether the given pattern entry is initialized.
   bool isInitialized(unsigned i) const {
      return getPatternList()[i].isInitialized();
   }

   Expr *getInit(unsigned i) const {
      return getPatternList()[i].getInit();
   }
   Expr *getExecutableInit(unsigned i) const {
      return getPatternList()[i].getExecutableInit();
   }
   Expr *getOriginalInit(unsigned i) const {
      return getPatternList()[i].getOriginalInit();
   }

   SourceRange getOriginalInitRange(unsigned i) const {
      return getPatternList()[i].getOriginalInitRange();
   }

   void setInit(unsigned i, Expr *E) {
      getMutablePatternList()[i].setInit(E);
   }

   Pattern *getPattern(unsigned i) const {
      return getPatternList()[i].getPattern();
   }

   void setPattern(unsigned i, Pattern *Pat, DeclContext *InitContext);

   DeclContext *getInitContext(unsigned i) const {
      return getPatternList()[i].getInitContext();
   }

   CaptureInfo getCaptureInfo(unsigned i) const {
      return getPatternList()[i].getCaptureInfo();
   }

   void setCaptureInfo(unsigned i, CaptureInfo captures) {
      getMutablePatternList()[i].setCaptureInfo(captures);
   }

   /// Given that this PBD is the parent pattern for the specified VarDecl,
   /// return the entry of the VarDecl in our PatternList.  For example, in:
   ///
   ///   let (a,b) = foo(), (c,d) = bar()
   ///
   /// "a" and "b" will have index 0, since they correspond to the first pattern,
   /// and "c" and "d" will have index 1 since they correspond to the second one.
   unsigned getPatternEntryIndexForVarDecl(const VarDecl *VD) const;

   bool isInitializerChecked(unsigned i) const {
      return getPatternList()[i].isInitializerChecked();
   }

   void setInitializerChecked(unsigned i) {
      getMutablePatternList()[i].setInitializerChecked();
   }

   bool isInitializerSubsumed(unsigned i) const {
      return getPatternList()[i].isInitializerSubsumed();
   }

   void setInitializerSubsumed(unsigned i) {
      getMutablePatternList()[i].setInitializerSubsumed();
   }

   /// Does this binding declare something that requires storage?
   bool hasStorage() const;

   /// Determines whether this binding either has an initializer expression, or is
   /// default initialized, without performing any type checking on it.
   bool isDefaultInitializable() const {
      for (unsigned i : range(getNumPatternEntries()))
         if (!isDefaultInitializable(i))
            return false;

      return true;
   }

   /// Can the pattern at index i be default initialized?
   bool isDefaultInitializable(unsigned i) const;

   /// Does this pattern have a user-provided initializer expression?
   bool isExplicitlyInitialized(unsigned i) const;

   /// Whether the pattern entry at the given index can generate a string
   /// representation of its initializer expression.
   bool hasInitStringRepresentation(unsigned i) const {
      return getPatternList()[i].hasInitStringRepresentation();
   }

   SourceLoc getEqualLoc(unsigned i) const;

   /// When the pattern binding contains only a single variable with no
   /// destructuring, retrieve that variable.
   VarDecl *getSingleVar() const;

   /// Return the first variable initialized by the pattern at the given index.
   VarDecl *getAnchoringVarDecl(unsigned i) const;

   bool isStatic() const { return Bits.PatternBindingDecl.IsStatic; }
   void setStatic(bool s) { Bits.PatternBindingDecl.IsStatic = s; }
   SourceLoc getStaticLoc() const { return StaticLoc; }
   /// \returns the way 'static'/'class' was spelled in the source.
   StaticSpellingKind getStaticSpelling() const {
      return static_cast<StaticSpellingKind>(
         Bits.PatternBindingDecl.StaticSpelling);
   }
   /// \returns the way 'static'/'class' should be spelled for this declaration.
   StaticSpellingKind getCorrectStaticSpelling() const;

   /// Is the pattern binding entry for this variable  currently being computed?
   bool isComputingPatternBindingEntry(const VarDecl *vd) const;

   /// Gets the text of the initializer expression for the pattern entry at the
   /// given index, stripping out inactive branches of any #ifs inside the
   /// expression.
   StringRef getInitStringRepresentation(unsigned i,
                                         SmallVectorImpl<char> &scratch) const {
      return getPatternList()[i].getInitStringRepresentation(scratch);
   }

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::PatternBinding;
   }

private:
   MutableArrayRef<PatternBindingEntry> getMutablePatternList() {
      // Pattern entries are tail allocated.
      return {getTrailingObjects<PatternBindingEntry>(), getNumPatternEntries()};
   }
};

/// TopLevelCodeDecl - This decl is used as a container for top-level
/// expressions and statements in the main module.  It is always a direct
/// child of a SourceFile.  The primary reason for building these is to give
/// top-level statements a DeclContext which is distinct from the file itself.
/// This, among other things, makes it easier to distinguish between local
/// top-level variables (which are not live past the end of the statement) and
/// global variables.
class TopLevelCodeDecl : public DeclContext, public Decl {
   BraceStmt *Body;
   SourceLoc getLocFromSource() const { return getStartLoc(); }
   friend class Decl;
public:
   TopLevelCodeDecl(DeclContext *Parent, BraceStmt *Body = nullptr)
      : DeclContext(DeclContextKind::TopLevelCodeDecl, Parent),
        Decl(DeclKind::TopLevelCode, Parent),
        Body(Body) {}

   BraceStmt *getBody() const { return Body; }
   void setBody(BraceStmt *b) { Body = b; }

   SourceLoc getStartLoc() const;
   SourceRange getSourceRange() const;

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::TopLevelCode;
   }
   static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDecl())
         return classof(D);
      return false;
   }

   using DeclContext::operator new;
};

/// SerializedTopLevelCodeDeclContext - This represents what was originally a
/// TopLevelCodeDecl during serialization. It is preserved only to maintain the
/// correct AST structure and remangling after deserialization.
class SerializedTopLevelCodeDeclContext : public SerializedLocalDeclContext {
public:
   SerializedTopLevelCodeDeclContext(DeclContext *Parent)
      : SerializedLocalDeclContext(LocalDeclContextKind::TopLevelCodeDecl,
                                   Parent) {}
   static bool classof(const DeclContext *DC) {
      if (auto LDC = dyn_cast<SerializedLocalDeclContext>(DC))
         return LDC->getLocalDeclContextKind() ==
                LocalDeclContextKind::TopLevelCodeDecl;
      return false;
   }
};

/// IfConfigDecl - This class represents #if/#else/#endif blocks.
/// Active and inactive block members are stored separately, with the intention
/// being that active members will be handed back to the enclosing context.
class IfConfigDecl : public Decl {
   /// An array of clauses controlling each of the #if/#elseif/#else conditions.
   /// The array is AstContext allocated.
   ArrayRef<IfConfigClause> Clauses;
   SourceLoc EndLoc;
   SourceLoc getLocFromSource() const { return Clauses[0].Loc; }
   friend class Decl;
public:

   IfConfigDecl(DeclContext *Parent, ArrayRef<IfConfigClause> Clauses,
                SourceLoc EndLoc, bool HadMissingEnd)
      : Decl(DeclKind::IfConfig, Parent), Clauses(Clauses), EndLoc(EndLoc)
   {
      Bits.IfConfigDecl.HadMissingEnd = HadMissingEnd;
   }

   ArrayRef<IfConfigClause> getClauses() const { return Clauses; }

   /// Return the active clause, or null if there is no active one.
   const IfConfigClause *getActiveClause() const {
      for (auto &Clause : Clauses)
         if (Clause.isActive) return &Clause;
      return nullptr;
   }

   const ArrayRef<AstNode> getActiveClauseElements() const {
      if (auto *Clause = getActiveClause())
         return Clause->Elements;
      return {};
   }

   SourceLoc getEndLoc() const { return EndLoc; }

   bool hadMissingEnd() const { return Bits.IfConfigDecl.HadMissingEnd; }

   SourceRange getSourceRange() const;

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::IfConfig;
   }
};

class StringLiteralExpr;

class PoundDiagnosticDecl : public Decl {
   SourceLoc StartLoc;
   SourceLoc EndLoc;
   StringLiteralExpr *Message;
   SourceLoc getLocFromSource() const { return StartLoc; }
   friend class Decl;
public:
   PoundDiagnosticDecl(DeclContext *Parent, bool IsError, SourceLoc StartLoc,
                       SourceLoc EndLoc, StringLiteralExpr *Message)
      : Decl(DeclKind::PoundDiagnostic, Parent), StartLoc(StartLoc),
        EndLoc(EndLoc), Message(Message) {
      Bits.PoundDiagnosticDecl.IsError = IsError;
      Bits.PoundDiagnosticDecl.HasBeenEmitted = false;
   }

   DiagnosticKind getKind() {
      return isError() ? DiagnosticKind::Error : DiagnosticKind::Warning;
   }

   StringLiteralExpr *getMessage() { return Message; }

   bool isError() {
      return Bits.PoundDiagnosticDecl.IsError;
   }

   bool hasBeenEmitted() {
      return Bits.PoundDiagnosticDecl.HasBeenEmitted;
   }

   void markEmitted() {
      Bits.PoundDiagnosticDecl.HasBeenEmitted = true;
   }

   SourceLoc getEndLoc() const { return EndLoc; };

   SourceRange getSourceRange() const {
      return SourceRange(StartLoc, EndLoc);
   }

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::PoundDiagnostic;
   }
};

class OpaqueTypeDecl;

/// ValueDecl - All named decls that are values in the language.  These can
/// have a type, etc.
class ValueDecl : public Decl {
   DeclName Name;
   SourceLoc NameLoc;
   llvm::PointerIntPair<Type, 3, OptionalEnum<AccessLevel>> TypeAndAccess;
   unsigned LocalDiscriminator = 0;

   struct {
      /// Whether the "IsObjC" bit has been computed yet.
      unsigned isObjCComputed : 1;

      /// Whether this declaration is exposed to Objective-C.
      unsigned isObjC : 1;

      /// Whether the "overridden" declarations have been computed already.
      unsigned hasOverriddenComputed : 1;

      /// Whether there are any "overridden" declarations. The actual overridden
      /// declarations are kept in a side table in the AstContext.
      unsigned hasOverridden : 1;

      /// Whether the "isDynamic" bit has been computed yet.
      unsigned isDynamicComputed : 1;

      /// Whether this declaration is 'dynamic', meaning that all uses of
      /// the declaration will go through an extra level of indirection that
      /// allows the entity to be replaced at runtime.
      unsigned isDynamic : 1;

      /// Whether the "isFinal" bit has been computed yet.
      unsigned isFinalComputed : 1;

      /// Whether this declaration is 'final'. A final class can't be subclassed,
      /// a final class member can't be overriden.
      unsigned isFinal : 1;

      /// Whether the "isIUO" bit" has been computed yet.
      unsigned isIUOComputed : 1;

      /// Whether this declaration produces an implicitly unwrapped
      /// optional result.
      unsigned isIUO : 1;
   } LazySemanticInfo = { };

   friend class DynamicallyReplacedDeclRequest;
   friend class OverriddenDeclsRequest;
   friend class IsObjCRequest;
   friend class IsFinalRequest;
   friend class IsDynamicRequest;
   friend class IsImplicitlyUnwrappedOptionalRequest;
   friend class InterfaceTypeRequest;
   friend class Decl;
   SourceLoc getLocFromSource() const { return NameLoc; }
protected:
   ValueDecl(DeclKind K,
             llvm::PointerUnion<DeclContext *, AstContext *> context,
             DeclName name, SourceLoc NameLoc)
      : Decl(K, context), Name(name), NameLoc(NameLoc) {
      Bits.ValueDecl.AlreadyInLookupTable = false;
      Bits.ValueDecl.CheckedRedeclaration = false;
      Bits.ValueDecl.IsUserAccessible = true;
   }

   // MemberLookupTable borrows a bit from this type
   friend class MemberLookupTable;
   bool isAlreadyInLookupTable() {
      return Bits.ValueDecl.AlreadyInLookupTable;
   }
   void setAlreadyInLookupTable(bool value = true) {
      Bits.ValueDecl.AlreadyInLookupTable = value;
   }

public:
   /// Return true if this Interface member is a Interface requirement.
   ///
   /// Asserts if this is not a member of a Interface.
   bool isInterfaceRequirement() const;

   /// Determine whether we have already checked whether this
   /// declaration is a redeclaration.
   bool alreadyCheckedRedeclaration() const {
      return Bits.ValueDecl.CheckedRedeclaration;
   }

   /// Set whether we have already checked this declaration as a
   /// redeclaration.
   void setCheckedRedeclaration(bool checked) {
      Bits.ValueDecl.CheckedRedeclaration = checked;
   }

   void setUserAccessible(bool Accessible) {
      Bits.ValueDecl.IsUserAccessible = Accessible;
   }

   bool isUserAccessible() const {
      return Bits.ValueDecl.IsUserAccessible;
   }

   bool hasName() const { return bool(Name); }
   bool isOperator() const { return Name.isOperator(); }

   /// Retrieve the full name of the declaration.
   /// TODO: Rename to getName?
   DeclName getFullName() const { return Name; }
   void setName(DeclName name) { Name = name; }

   /// Retrieve the base name of the declaration, ignoring any argument
   /// names.
   DeclBaseName getBaseName() const { return Name.getBaseName(); }

   /// @todo
   /// Retrieve the name to use for this declaration when interoperating
   /// with the Objective-C runtime.
   ///
   /// \returns A "selector" containing the runtime name. For non-method
   /// entities (classes, Interfaces, properties), this operation will
   /// return a zero-parameter selector with the appropriate name in its
   /// first slot.
//   Optional<ObjCSelector> getObjCRuntimeName(
//      bool skipIsObjCResolution = false) const;

   /// Determine whether the given declaration can infer @objc, or the
   /// Objective-C name, if used to satisfy the given requirement.
//   bool canInferObjCFromRequirement(ValueDecl *requirement);

   SourceLoc getNameLoc() const { return NameLoc; }

   bool isUsableFromInline() const;

   /// Returns \c true if this declaration is *not* intended to be used directly
   /// by application developers despite the visibility.
   bool shouldHideFromEditor() const;

   bool hasAccess() const {
      return TypeAndAccess.getInt().hasValue();
   }

   /// Access control is done by Requests.
   friend class AccessLevelRequest;

   /// Returns the access level specified explicitly by the user, or provided by
   /// default according to language rules.
   ///
   /// Most of the time this is not the interesting value to check; access is
   /// limited by enclosing scopes per SE-0025. Use #getFormalAccessScope to
   /// check if access control is being used consistently, and to take features
   /// such as \c \@testable and \c \@usableFromInline into account.
   ///
   /// \sa getFormalAccessScope
   /// \sa hasOpenAccess
   AccessLevel getFormalAccess() const;

   /// Determine whether this Decl has either Private or FilePrivate access,
   /// and its DeclContext does not.
   bool isOutermostPrivateOrFilePrivateScope() const;

   /// Returns the outermost DeclContext from which this declaration can be
   /// accessed, or null if the declaration is public.
   ///
   /// This is used when calculating if access control is being used
   /// consistently. If \p useDC is provided (the location where the value is
   /// being used), features that affect formal access such as \c \@testable are
   /// taken into account.
   ///
   /// \invariant
   /// <code>value.isAccessibleFrom(
   ///     value.getFormalAccessScope().getDeclContext())</code>
   ///
   /// If \p treatUsableFromInlineAsPublic is true, declarations marked with the
   /// \c \@usableFromInline attribute are treated as public. This is normally
   /// false for name lookup and other source language concerns, but true when
   /// computing the linkage of generated functions.
   ///
   /// \sa getFormalAccess
   /// \sa isAccessibleFrom
   /// \sa hasOpenAccess
   AccessScope
   getFormalAccessScope(const DeclContext *useDC = nullptr,
                        bool treatUsableFromInlineAsPublic = false) const;


   /// Copy the formal access level and @usableFromInline attribute from
   /// \p source.
   ///
   /// If \p sourceIsParentContext is true, an access level of \c private will
   /// be copied as \c fileprivate, to ensure that this declaration will be
   /// available everywhere \p source is.
   void copyFormalAccessFrom(const ValueDecl *source,
                             bool sourceIsParentContext = false);

   /// Returns the access level that actually controls how a declaration should
   /// be emitted and may be used.
   ///
   /// This is the access used when making optimization and code generation
   /// decisions. It should not be used at the AST or semantic level.
   AccessLevel getEffectiveAccess() const;

   void setAccess(AccessLevel access) {
      assert(!hasAccess() && "access already set");
      overwriteAccess(access);
   }

   /// Overwrite the access of this declaration.
   ///
   /// This is needed in the LLDB REPL.
   void overwriteAccess(AccessLevel access) {
      TypeAndAccess.setInt(access);
   }

   /// Returns true if this declaration is accessible from the given context.
   ///
   /// A private declaration is accessible from any DeclContext within the same
   /// source file.
   ///
   /// An internal declaration is accessible from any DeclContext within the same
   /// module.
   ///
   /// A public declaration is accessible everywhere.
   ///
   /// If \p DC is null, returns true only if this declaration is public.
   ///
   /// If \p forConformance is true, we ignore the visibility of the Interface
   /// when evaluating Interface extension members. This language rule allows a
   /// Interface extension of a private Interface to provide default
   /// implementations for the requirements of a public Interface, even when
   /// the default implementations are not visible to name lookup.
   bool isAccessibleFrom(const DeclContext *DC,
                         bool forConformance = false) const;

   /// Returns whether this declaration should be treated as \c open from
   /// \p useDC. This is very similar to #getFormalAccess, but takes
   /// \c \@testable into account.
   ///
   /// This is mostly only useful when considering requirements on an override:
   /// if the base declaration is \c open, the override might have to be too.
   bool hasOpenAccess(const DeclContext *useDC) const;

   /// FIXME: This is deprecated.
   bool isRecursiveValidation() const;

   /// Retrieve the "interface" type of this value, which uses
   /// GenericTypeParamType if the declaration is generic. For a generic
   /// function, this will have a GenericFunctionType with a
   /// GenericSignature inside the type.
   Type getInterfaceType() const;
   bool hasInterfaceType() const;

   /// Set the interface type for the given value.
   void setInterfaceType(Type type);

   /// isInstanceMember - Determine whether this value is an instance member
   /// of an enum or Interface.
   bool isInstanceMember() const;

   /// Retrieve the context discriminator for this local value, which
   /// is the index of this declaration in the sequence of
   /// discriminated declarations with the same name in the current
   /// context.  Only local functions and variables with getters and
   /// setters have discriminators.
   unsigned getLocalDiscriminator() const;
   void setLocalDiscriminator(unsigned index);

   /// Retrieve the declaration that this declaration overrides, if any.
   ValueDecl *getOverriddenDecl() const;

   /// Retrieve the declarations that this declaration overrides, if any.
   llvm::TinyPtrVector<ValueDecl *> getOverriddenDecls() const;

   /// Set the declaration that this declaration overrides.
   void setOverriddenDecl(ValueDecl *overridden) {
      setOverriddenDecls(overridden);
   }

   /// Set the declarations that this declaration overrides.
   void setOverriddenDecls(ArrayRef<ValueDecl *> overridden);

   /// Whether the overridden declarations have already been computed.
   bool overriddenDeclsComputed() const;

   /// Compute the untyped overload signature for this declaration.
   OverloadSignature getOverloadSignature() const;

   /// Retrieve the type used to describe this entity for the purposes of
   /// overload resolution.
   CanType getOverloadSignatureType() const;

   /// Returns true if the decl requires Objective-C interop.
   ///
   /// This can be true even if there is no 'objc' attribute on the declaration.
   /// In that case it was inferred by the type checker and set with a call to
   /// markAsObjC().
//   bool isObjC() const;

   /// Note whether this declaration is known to be exposed to Objective-C.
//   void setIsObjC(bool Value);

   /// Is this declaration 'final'?
   bool isFinal() const;

   /// Is this declaration marked with 'dynamic'?
   bool isDynamic() const;

//   bool isObjCDynamic() const {
//      return isObjC() && isDynamic();
//   }

   bool isNativeDynamic() const {
      return /*!isObjC() && */isDynamic();
   }

   /// Set whether this type is 'dynamic' or not.
   void setIsDynamic(bool value);

   /// Whether the 'dynamic' bit has been computed already.
   bool isDynamicComputed() const {
      return LazySemanticInfo.isDynamicComputed;
   }

   /// Returns true if this decl can be found by id-style dynamic lookup.
   bool canBeAccessedByDynamicLookup() const;

   /// Returns true if this declaration has an implicitly unwrapped optional
   /// result. The precise meaning depends on the declaration kind:
   /// - for properties, the value is IUO
   /// - for subscripts, the element type is IUO
   /// - for functions, the result type is IUO
   /// - for constructors, the failability kind is IUO
   bool isImplicitlyUnwrappedOptional() const;

   /// Should only be set on imported and deserialized declarations; parsed
   /// declarations compute this lazily via a request.
   void setImplicitlyUnwrappedOptional(bool isIUO) {
      LazySemanticInfo.isIUOComputed = 1;
      LazySemanticInfo.isIUO = isIUO;
   }

   /// Returns the Interface requirements that this decl conforms to.
   ArrayRef<ValueDecl *>
   getSatisfiedInterfaceRequirements(bool Sorted = false) const;

   /// Determines the kind of access that should be performed by a
   /// DeclRefExpr or MemberRefExpr use of this value in the specified
   /// context.
   ///
   /// \param DC The declaration context.
   ///
   /// \param isAccessOnSelf Whether this is a member access on the implicit
   ///        'self' declaration of the declaration context.
   AccessSemantics getAccessSemanticsFromContext(const DeclContext *DC,
                                                 bool isAccessOnSelf) const;

   /// Print a reference to the given declaration.
   std::string printRef() const;

   /// Dump a reference to the given declaration.
   void dumpRef(raw_ostream &os) const;

   /// Dump a reference to the given declaration.
   POLAR_DEBUG_DUMPER(dumpRef());

   /// Returns true if the declaration is a static member of a type.
   ///
   /// This is not necessarily the opposite of "isInstanceMember()". Both
   /// predicates will be false for declarations that either categorically
   /// can't be "static" or are in a context where "static" doesn't make sense.
   bool isStatic() const;

   /// Retrieve the location at which we should insert a new attribute or
   /// modifier.
   SourceLoc getAttributeInsertionLoc(bool forModifier) const;

   static bool classof(const Decl *D) {
      return D->getKind() >= DeclKind::First_ValueDecl &&
             D->getKind() <= DeclKind::Last_ValueDecl;
   }

   /// True if this is a C function that was imported as a member of a type in
   /// Swift.
   bool isImportAsMember() const;

   /// Returns true if the declaration's interface type is a function type with a
   /// curried self parameter.
   bool hasCurriedSelf() const;

   /// Returns true if the declaration has a parameter list associated with it.
   ///
   /// Note that not all declarations with function interface types have
   /// parameter lists, for example an enum element without associated values.
   bool hasParameterList() const;

   /// Returns the number of curry levels in the declaration's interface type.
   unsigned getNumCurryLevels() const;

   /// Get the decl for this value's opaque result type, if it has one.
   OpaqueTypeDecl *getOpaqueResultTypeDecl() const;

   /// Get the representative for this value's opaque result type, if it has one.
   OpaqueReturnTypeRepr *getOpaqueResultTypeRepr() const;

   /// Retrieve the attribute associating this declaration with a
   /// function builder, if there is one.
   CustomAttr *getAttachedFunctionBuilder() const;

   /// Retrieve the @functionBuilder type attached to this declaration,
   /// if there is one.
   Type getFunctionBuilderType() const;

   /// If this value or its backing storage is annotated
   /// @_dynamicReplacement(for: ...), compute the original declaration
   /// that this declaration dynamically replaces.
   ValueDecl *getDynamicallyReplacedDecl() const;
};

/// This is a common base class for declarations which declare a type.
class TypeDecl : public ValueDecl {
   MutableArrayRef<TypeLoc> Inherited;

protected:
   TypeDecl(DeclKind K, llvm::PointerUnion<DeclContext *, AstContext *> context,
            Identifier name, SourceLoc NameLoc,
            MutableArrayRef<TypeLoc> inherited) :
      ValueDecl(K, context, name, NameLoc), Inherited(inherited) {}

public:
   Identifier getName() const { return getFullName().getBaseIdentifier(); }

   /// Returns the string for the base name, or "_" if this is unnamed.
   StringRef getNameStr() const {
      assert(!getFullName().isSpecial() && "Cannot get string for special names");
      return hasName() ? getBaseName().getIdentifier().str() : "_";
   }

   /// The type of this declaration's values. For the type of the
   /// declaration itself, use getInterfaceType(), which returns a
   /// metatype.
   Type getDeclaredInterfaceType() const;

   /// Retrieve the set of Interfaces that this type inherits (i.e,
   /// explicitly conforms to).
   MutableArrayRef<TypeLoc> getInherited() { return Inherited; }
   ArrayRef<TypeLoc> getInherited() const { return Inherited; }

   void setInherited(MutableArrayRef<TypeLoc> i) { Inherited = i; }

   static bool classof(const Decl *D) {
      return D->getKind() >= DeclKind::First_TypeDecl &&
             D->getKind() <= DeclKind::Last_TypeDecl;
   }

   /// Compute an ordering between two type declarations that is ABI-stable.
   static int compare(const TypeDecl *type1, const TypeDecl *type2);

   /// Compute an ordering between two type declarations that is ABI-stable.
   /// This version takes a pointer-to-a-pointer for use with
   /// llvm::array_pod_sort() and similar.
   template<typename T>
   static int compare(T * const* type1, T * const* type2) {
      return compare(*type1, *type2);
   }
};

/// A type declaration that can have generic parameters attached to it. Because
/// it has these generic parameters, it is always a DeclContext.
class GenericTypeDecl : public GenericContext, public TypeDecl {
public:
   GenericTypeDecl(DeclKind K, DeclContext *DC,
                   Identifier name, SourceLoc nameLoc,
                   MutableArrayRef<TypeLoc> inherited,
                   GenericParamList *GenericParams);

   // Resolve ambiguity due to multiple base classes.
   using TypeDecl::getAstContext;
   using DeclContext::operator new;
   using TypeDecl::getDeclaredInterfaceType;

   static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDecl())
         return classof(D);
      return false;
   }
   static bool classof(const Decl *D) {
      return D->getKind() >= DeclKind::First_GenericTypeDecl &&
             D->getKind() <= DeclKind::Last_GenericTypeDecl;
   }
};

/// OpaqueTypeDecl - This is a declaration of an opaque type. The opaque type
/// is formally equivalent to its underlying type, but abstracts it away from
/// clients of the opaque type, only exposing the type as something conforming
/// to a given set of constraints.
///
/// Currently, opaque types do not normally have an explicit spelling in source
/// code. One is formed implicitly when a declaration is written with an opaque
/// result type, as in:
///
/// func foo() -> opaque SignedInteger { return 1 }
///
/// The declared type is a special kind of ArchetypeType representing the
/// abstracted underlying type.
class OpaqueTypeDecl : public GenericTypeDecl {
   /// The original declaration that "names" the opaque type. Although a specific
   /// opaque type cannot be explicitly named, oapque types can propagate
   /// arbitrarily through expressions, so we need to know *which* opaque type is
   /// propagated.
   ValueDecl *NamingDecl;

   /// The generic signature of the opaque interface to the type. This is the
   /// outer generic signature with an added generic parameter representing the
   /// underlying type.
   GenericSignature OpaqueInterfaceGenericSignature;

   /// The generic parameter that represents the underlying type.
   GenericTypeParamType *UnderlyingInterfaceType;

   /// If known, the underlying type and conformances of the opaque type,
   /// expressed as a SubstitutionMap for the opaque interface generic signature.
   /// This maps types in the interface generic signature to the outer generic
   /// signature of the original declaration.
   Optional<SubstitutionMap> UnderlyingTypeSubstitutions;

   mutable Identifier OpaqueReturnTypeIdentifier;

public:
   OpaqueTypeDecl(ValueDecl *NamingDecl,
                  GenericParamList *GenericParams,
                  DeclContext *DC,
                  GenericSignature OpaqueInterfaceGenericSignature,
                  GenericTypeParamType *UnderlyingInterfaceType);

   ValueDecl *getNamingDecl() const { return NamingDecl; }

   void setNamingDecl(ValueDecl *D) {
      assert(!NamingDecl && "already have naming decl");
      NamingDecl = D;
   }

   /// Is this opaque type the opaque return type of the given function?
   ///
   /// This is more complex than just checking `getNamingDecl` because the
   /// function could also be the getter of a storage declaration.
   bool isOpaqueReturnTypeOfFunction(const AbstractFunctionDecl *func) const;

   GenericSignature getOpaqueInterfaceGenericSignature() const {
      return OpaqueInterfaceGenericSignature;
   }

   GenericTypeParamType *getUnderlyingInterfaceType() const {
      return UnderlyingInterfaceType;
   }

   Optional<SubstitutionMap> getUnderlyingTypeSubstitutions() const {
      return UnderlyingTypeSubstitutions;
   }

   void setUnderlyingTypeSubstitutions(SubstitutionMap subs) {
      assert(!UnderlyingTypeSubstitutions.hasValue() && "resetting underlying type?!");
      UnderlyingTypeSubstitutions = subs;
   }

   // Opaque type decls are currently always implicit
   SourceRange getSourceRange() const { return SourceRange(); }

   // Get the identifier string that can be used to cross-reference unnamed
   // opaque return types across files.
   Identifier getOpaqueReturnTypeIdentifier() const;

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::OpaqueType;
   }
   static bool classof(const GenericTypeDecl *D) {
      return D->getKind() == DeclKind::OpaqueType;
   }
   static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDecl())
         return classof(D);
      return false;
   }
};

/// TypeAliasDecl - This is a declaration of a typealias, for example:
///
///    typealias Foo = Int
///
/// TypeAliasDecl's always have 'MetatypeType' type.
///
class TypeAliasDecl : public GenericTypeDecl {
   friend class UnderlyingTypeRequest;

   /// The location of the 'typealias' keyword
   SourceLoc TypeAliasLoc;

   /// The location of the equal '=' token
   SourceLoc EqualLoc;

   /// The end of the type, valid even when the type cannot be parsed
   SourceLoc TypeEndLoc;

   /// The location of the right-hand side of the typealias binding
   TypeLoc UnderlyingTy;

public:
   TypeAliasDecl(SourceLoc TypeAliasLoc, SourceLoc EqualLoc, Identifier Name,
                 SourceLoc NameLoc, GenericParamList *GenericParams,
                 DeclContext *DC);

   SourceLoc getStartLoc() const { return TypeAliasLoc; }
   SourceRange getSourceRange() const;

   /// Returns the location of the equal '=' token
   SourceLoc getEqualLoc() const {
      return EqualLoc;
   }

   void setTypeEndLoc(SourceLoc e) { TypeEndLoc = e; }

   /// Retrieve the TypeRepr corresponding to the parsed underlying type.
   TypeRepr *getUnderlyingTypeRepr() const {
      return UnderlyingTy.getTypeRepr();
   }
   void setUnderlyingTypeRepr(TypeRepr *repr) {
      UnderlyingTy = repr;
   }

   /// Retrieve the interface type of the underlying type.
   Type getUnderlyingType() const;
   void setUnderlyingType(Type type);

   /// For generic typealiases, return the unbound generic type.
   UnboundGenericType *getUnboundGenericType() const;

   /// Retrieve a sugared interface type containing the structure of the interface
   /// type before any semantic validation has occured.
   Type getStructuralType() const;

   bool isCompatibilityAlias() const {
      return Bits.TypeAliasDecl.IsCompatibilityAlias;
   }

   void markAsCompatibilityAlias(bool newValue = true) {
      Bits.TypeAliasDecl.IsCompatibilityAlias = newValue;
   }

   /// Is this a special debugger variable?
   bool isDebuggerAlias() const { return Bits.TypeAliasDecl.IsDebuggerAlias; }
   void markAsDebuggerAlias(bool isDebuggerAlias) {
      Bits.TypeAliasDecl.IsDebuggerAlias = isDebuggerAlias;
   }

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::TypeAlias;
   }
   static bool classof(const GenericTypeDecl *D) {
      return D->getKind() == DeclKind::TypeAlias;
   }
   static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDecl())
         return classof(D);
      return false;
   }
};

/// Abstract class describing generic type parameters and associated types,
/// whose common purpose is to anchor the abstract type parameter and specify
/// requirements for any corresponding type argument.
class AbstractTypeParamDecl : public TypeDecl {
protected:
   AbstractTypeParamDecl(DeclKind kind, DeclContext *dc, Identifier name,
                         SourceLoc NameLoc)
      : TypeDecl(kind, dc, name, NameLoc, { }) { }

public:
   /// Return the superclass of the generic parameter.
   Type getSuperclass() const;

   /// Retrieve the set of Interfaces to which this abstract type
   /// parameter conforms.
   ArrayRef<InterfaceDecl *> getConformingInterfaces() const;

   static bool classof(const Decl *D) {
      return D->getKind() >= DeclKind::First_AbstractTypeParamDecl &&
             D->getKind() <= DeclKind::Last_AbstractTypeParamDecl;
   }
};

/// A declaration of a generic type parameter.
///
/// A generic type parameter introduces a new, named type parameter along
/// with some set of requirements on any type argument used to realize this
/// type parameter. The requirements involve conformances to specific
/// Interfaces or inheritance from a specific class type.
///
/// In the following example, 'T' is a generic type parameter with the
/// requirement that the type argument conform to the 'Comparable' Interface.
///
/// \code
/// func min<T : Comparable>(x : T, y : T) -> T { ... }
/// \endcode
class GenericTypeParamDecl : public AbstractTypeParamDecl {
public:
   static const unsigned InvalidDepth = 0xFFFF;

   /// Construct a new generic type parameter.
   ///
   /// \param dc The DeclContext in which the generic type parameter's owner
   /// occurs. This should later be overwritten with the actual declaration
   /// context that owns the type parameter.
   ///
   /// \param name The name of the generic parameter.
   /// \param nameLoc The location of the name.
   GenericTypeParamDecl(DeclContext *dc, Identifier name, SourceLoc nameLoc,
                        unsigned depth, unsigned index);

   /// The depth of this generic type parameter, i.e., the number of outer
   /// levels of generic parameter lists that enclose this type parameter.
   ///
   /// \code
   /// struct X<T> {
   ///   func f<U>() { }
   /// }
   /// \endcode
   ///
   /// Here 'T' has depth 0 and 'U' has depth 1. Both have index 0.
   unsigned getDepth() const { return Bits.GenericTypeParamDecl.Depth; }

   /// Set the depth of this generic type parameter.
   ///
   /// \sa getDepth
   void setDepth(unsigned depth) {
      Bits.GenericTypeParamDecl.Depth = depth;
      assert(Bits.GenericTypeParamDecl.Depth == depth && "Truncation");
   }

   /// The index of this generic type parameter within its generic parameter
   /// list.
   ///
   /// \code
   /// struct X<T, U> {
   ///   func f<V>() { }
   /// }
   /// \endcode
   ///
   /// Here 'T' and 'U' have indexes 0 and 1, respectively. 'V' has index 0.
   unsigned getIndex() const { return Bits.GenericTypeParamDecl.Index; }

   SourceLoc getStartLoc() const { return getNameLoc(); }
   SourceRange getSourceRange() const;

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::GenericTypeParam;
   }
};

/// A declaration of an associated type.
///
/// An associated type introduces a new, named type in a Interface that
/// can vary from one conforming type to the next. Associated types have a
/// set of requirements to which the type that replaces it much realize,
/// described via conformance to specific Interfaces, or inheritance from a
/// specific class type.
///
/// In the following example, 'Element' is an associated type with no
/// requirements.
///
/// \code
/// Interface Enumerator {
///   typealias Element
///   func getNext() -> Element?
/// }
/// \endcode
class AssociatedTypeDecl : public AbstractTypeParamDecl {
   /// The location of the initial keyword.
   SourceLoc KeywordLoc;

   /// The default definition.
   TypeRepr *DefaultDefinition;

   /// The where clause attached to the associated type.
   TrailingWhereClause *TrailingWhere;

   LazyMemberLoader *Resolver = nullptr;
   uint64_t ResolverContextData;

   friend class DefaultDefinitionTypeRequest;

public:
   AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name,
                      SourceLoc nameLoc, TypeRepr *defaultDefinition,
                      TrailingWhereClause *trailingWhere);
   AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name,
                      SourceLoc nameLoc, TrailingWhereClause *trailingWhere,
                      LazyMemberLoader *definitionResolver,
                      uint64_t resolverData);

   /// Get the Interface in which this associated type is declared.
   InterfaceDecl *getInterface() const {
      return cast<InterfaceDecl>(getDeclContext());
   }

   /// Check if we have a default definition type.
   bool hasDefaultDefinitionType() const {
      // If we have a TypeRepr, return true immediately without kicking off
      // a request.
      return DefaultDefinition || getDefaultDefinitionType();
   }

   /// Retrieve the default definition type.
   Type getDefaultDefinitionType() const;

   /// Retrieve the default definition as written in the source.
   TypeRepr *getDefaultDefinitionTypeRepr() const {
      return DefaultDefinition;
   }

   /// Retrieve the trailing where clause for this associated type, if any.
   TrailingWhereClause *getTrailingWhereClause() const { return TrailingWhere; }

   /// Set the trailing where clause for this associated type.
   void setTrailingWhereClause(TrailingWhereClause *trailingWhereClause) {
      TrailingWhere = trailingWhereClause;
   }

   /// Retrieve the associated type "anchor", which is the associated type
   /// declaration that will be used to describe this associated type in the
   /// ABI.
   ///
   /// The associated type "anchor" is an associated type that does not
   /// override any other associated type. There may be several such associated
   /// types; select one deterministically.
   AssociatedTypeDecl *getAssociatedTypeAnchor() const;

   /// Retrieve the (first) overridden associated type declaration, if any.
   AssociatedTypeDecl *getOverriddenDecl() const {
      return cast_or_null<AssociatedTypeDecl>(
         AbstractTypeParamDecl::getOverriddenDecl());
   }

   /// Retrieve the set of associated types overridden by this associated
   /// type.
   llvm::TinyPtrVector<AssociatedTypeDecl *> getOverriddenDecls() const;

   SourceLoc getStartLoc() const { return KeywordLoc; }
   SourceRange getSourceRange() const;

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::AssociatedType;
   }
};

class MemberLookupTable;
class ConformanceLookupTable;

// Kinds of pointer types.
enum PointerTypeKind : unsigned {
   PTK_UnsafeMutableRawPointer,
   PTK_UnsafeRawPointer,
   PTK_UnsafeMutablePointer,
   PTK_UnsafePointer,
   PTK_AutoreleasingUnsafeMutablePointer,
};

static inline bool isRawPointerKind(PointerTypeKind PTK) {
   switch (PTK) {
      case PTK_UnsafeMutableRawPointer:
      case PTK_UnsafeRawPointer:
         return true;
      case PTK_UnsafeMutablePointer:
      case PTK_UnsafePointer:
      case PTK_AutoreleasingUnsafeMutablePointer:
         return false;
   }

   llvm_unreachable("Unhandled PointerTypeKind in switch.");
}

// Kinds of buffer pointer types.
enum BufferPointerTypeKind : unsigned {
   BPTK_UnsafeMutableRawBufferPointer,
   BPTK_UnsafeRawBufferPointer,
   BPTK_UnsafeMutableBufferPointer,
   BPTK_UnsafeBufferPointer,
};

enum KeyPathTypeKind : unsigned char {
   KPTK_AnyKeyPath,
   KPTK_PartialKeyPath,
   KPTK_KeyPath,
   KPTK_WritableKeyPath,
   KPTK_ReferenceWritableKeyPath
};

/// NominalTypeDecl - a declaration of a nominal type, like a struct.
class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
   SourceRange Braces;

   /// The first extension of this type.
   ExtensionDecl *FirstExtension = nullptr;

   /// The last extension of this type, used solely for efficient
   /// insertion of new extensions.
   ExtensionDecl *LastExtension = nullptr;

   /// The generation at which we last loaded extensions.
   unsigned ExtensionGeneration;

   /// Prepare to traverse the list of extensions.
   void prepareExtensions();

   /// Retrieve the conformance loader (if any), and removing it in the
   /// same operation. The caller is responsible for loading the
   /// conformances.
   std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoader() {
      if (!Bits.NominalTypeDecl.HasLazyConformances)
         return { nullptr, 0 };

      return takeConformanceLoaderSlow();
   }

   /// Slow path for \c takeConformanceLoader().
   std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoaderSlow();

   /// A lookup table containing all of the members of this type and
   /// its extensions.
   ///
   /// The table itself is lazily constructed and updated when
   /// lookupDirect() is called. The bit indicates whether the lookup
   /// table has already added members by walking the declarations in
   /// scope; it should be manipulated through \c isLookupTablePopulated()
   /// and \c setLookupTablePopulated().
   llvm::PointerIntPair<MemberLookupTable *, 1, bool> LookupTable;

   /// Prepare the lookup table to make it ready for lookups.
   void prepareLookupTable();

   /// True if the entries in \c LookupTable are complete--that is, if a
   /// name is present, it contains all members with that name.
   bool isLookupTablePopulated() const;
   void setLookupTablePopulated(bool value);

   /// Note that we have added a member into the iterable declaration context,
   /// so that it can also be added to the lookup table (if needed).
   void addedMember(Decl *member);

   /// Note that we have added an extension into the nominal type,
   /// so that its members can eventually be added to the lookup table.
   void addedExtension(ExtensionDecl *ext);

   /// A lookup table used to find the Interface conformances of
   /// a given nominal type.
   mutable ConformanceLookupTable *ConformanceTable = nullptr;

   /// Prepare the conformance table.
   void prepareConformanceTable() const;

   /// Returns the Interface requirements that \c Member conforms to.
   ArrayRef<ValueDecl *>
   getSatisfiedInterfaceRequirementsForMember(const ValueDecl *Member,
                                             bool Sorted) const;

   friend class AstContext;
   friend class MemberLookupTable;
   friend class ConformanceLookupTable;
   friend class ExtensionDecl;
   friend class DeclContext;
   friend class IterableDeclContext;
   friend ArrayRef<ValueDecl *>
   ValueDecl::getSatisfiedInterfaceRequirements(bool Sorted) const;

protected:
   Type DeclaredTy;
   Type DeclaredInterfaceTy;

   NominalTypeDecl(DeclKind K, DeclContext *DC, Identifier name,
                   SourceLoc NameLoc,
                   MutableArrayRef<TypeLoc> inherited,
                   GenericParamList *GenericParams) :
      GenericTypeDecl(K, DC, name, NameLoc, inherited, GenericParams),
      IterableDeclContext(IterableDeclContextKind::NominalTypeDecl)
   {
      Bits.NominalTypeDecl.AddedImplicitInitializers = false;
      ExtensionGeneration = 0;
      Bits.NominalTypeDecl.HasLazyConformances = false;
      Bits.NominalTypeDecl.IsComputingSemanticMembers = false;
   }

   friend class InterfaceType;

public:
   using GenericTypeDecl::getAstContext;

   SourceRange getBraces() const { return Braces; }

   void setBraces(SourceRange braces) { Braces = braces; }

   /// Should this declaration behave as if it must be accessed
   /// resiliently, even when we're building a non-resilient module?
   ///
   /// This is used for diagnostics, because we do not want a behavior
   /// change between builds with resilience enabled and disabled.
   bool isFormallyResilient() const;

   /// Do we need to use resilient access patterns outside of this type's
   /// resilience domain?
   bool isResilient() const;

   /// Do we need to use resilient access patterns when accessing this
   /// type from the given module?
   bool isResilient(ModuleDecl *M, ResilienceExpansion expansion) const;

   /// Determine whether we have already attempted to add any
   /// implicitly-defined initializers to this declaration.
   bool addedImplicitInitializers() const {
      return Bits.NominalTypeDecl.AddedImplicitInitializers;
   }

   /// Note that we have attempted to add implicit initializers.
   void setAddedImplicitInitializers() {
      Bits.NominalTypeDecl.AddedImplicitInitializers = true;
   }

   /// getDeclaredType - Retrieve the type declared by this entity, without
   /// any generic parameters bound if this is a generic type.
   Type getDeclaredType() const;

   /// getDeclaredInterfaceType - Retrieve the type declared by this entity, with
   /// generic parameters bound if this is a generic type.
   Type getDeclaredInterfaceType() const;

   /// Add a new extension to this nominal type.
   void addExtension(ExtensionDecl *extension);

   /// Retrieve the set of extensions of this type.
   ExtensionRange getExtensions();

   /// Special-behaviour flags passed to lookupDirect()
   enum class LookupDirectFlags {
      /// Whether to include @_implements members.
      /// Used by conformance-checking to find special @_implements members.
         IncludeAttrImplements = 1 << 0,
   };

   /// Find all of the declarations with the given name within this nominal type
   /// and its extensions.
   ///
   /// This routine does not look into superclasses, nor does it consider
   /// Interfaces to which the nominal type conforms. Furthermore, the resulting
   /// set of declarations has not been filtered for visibility, nor have
   /// overridden declarations been removed.
   TinyPtrVector<ValueDecl *> lookupDirect(DeclName name,
                                           OptionSet<LookupDirectFlags> flags =
                                           OptionSet<LookupDirectFlags>());

   /// Collect the set of Interfaces to which this type should implicitly
   /// conform, such as AnyObject (for classes).
   void getImplicitInterfaces(SmallVectorImpl<InterfaceDecl *> &Interfaces);

   /// Look for conformances of this nominal type to the given
   /// Interface.
   ///
   /// \param module The module from which we initiate the search.
   /// FIXME: This is currently unused.
   ///
   /// \param Interface The Interface whose conformance is requested.
   /// \param conformances Will be populated with the set of Interface
   /// conformances found for this Interface.
   ///
   /// \returns true if any conformances were found.
   bool lookupConformance(
      ModuleDecl *module, InterfaceDecl *Interface,
      SmallVectorImpl<InterfaceConformance *> &conformances) const;

   /// Retrieve all of the Interfaces that this nominal type conforms to.
   SmallVector<InterfaceDecl *, 2> getAllInterfaces() const;

   /// Retrieve all of the Interface conformances for this nominal type.
   SmallVector<InterfaceConformance *, 2> getAllConformances(
      bool sorted = false) const;

   /// Register an externally-created Interface conformance in the
   /// conformance lookup table.
   ///
   /// This is used by deserialization of module files to report
   /// conformances.
   void registerInterfaceConformance(InterfaceConformance *conformance);

   void setConformanceLoader(LazyMemberLoader *resolver, uint64_t contextData);

   /// Is this the decl for Optional<T>?
   bool isOptionalDecl() const;

   /// Is this a key path type?
   Optional<KeyPathTypeKind> getKeyPathTypeKind() const;

   /// Retrieve information about this type as a property wrapper.
   PropertyWrapperTypeInfo getPropertyWrapperTypeInfo() const;

   /// Return a collection of the stored member variables of this type.
   ArrayRef<VarDecl *> getStoredProperties() const;

   /// Return a collection of the stored member variables of this type, along
   /// with placeholders for unimportable stored properties.
   ArrayRef<Decl *> getStoredPropertiesAndMissingMemberPlaceholders() const;

   /// Return the range of semantics attributes attached to this NominalTypeDecl.
   auto getSemanticsAttrs() const
   -> decltype(getAttrs().getAttributes<SemanticsAttr>()) {
      return getAttrs().getAttributes<SemanticsAttr>();
   }

   bool hasSemanticsAttr(StringRef attrValue) const {
      return llvm::any_of(getSemanticsAttrs(), [&](const SemanticsAttr *attr) {
         return attrValue.equals(attr->Value);
      });
   }

   /// Whether this declaration has a synthesized memberwise initializer.
   bool hasMemberwiseInitializer() const;

   /// Retrieves the synthesized memberwise initializer for this declaration,
   /// or \c nullptr if it does not have one.
   ConstructorDecl *getMemberwiseInitializer() const;

   /// Whether this declaration has a synthesized zero parameter default
   /// initializer.
   bool hasDefaultInitializer() const;

   /// Retrieves the synthesized zero parameter default initializer for this
   /// declaration, or \c nullptr if it doesn't have one.
   ConstructorDecl *getDefaultInitializer() const;

   void synthesizeSemanticMembersIfNeeded(DeclName member);

   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
      return D->getKind() >= DeclKind::First_NominalTypeDecl &&
             D->getKind() <= DeclKind::Last_NominalTypeDecl;
   }
   static bool classof(const GenericTypeDecl *D) {
      return D->getKind() >= DeclKind::First_NominalTypeDecl &&
             D->getKind() <= DeclKind::Last_NominalTypeDecl;
   }

   static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDecl())
         return classof(D);
      return false;
   }
   static bool classof(const IterableDeclContext *C) {
      return C->getIterableContextKind()
             == IterableDeclContextKind::NominalTypeDecl;
   }
   static bool classof(const NominalTypeDecl *D) { return true; }
   static bool classof(const ExtensionDecl *D) { return false; }
};

/// This is the declaration of an enum.
///
/// For example:
///
/// \code
///    enum Bool {
///      case false
///      case true
///    }
///
///    enum Optional<T> {
///      case none
///      case some(T)
///    }
/// \endcode
///
/// The type of the decl itself is a MetatypeType; use getDeclaredType()
/// to get the declared type ("Bool" or "Optional" in the above example).
class EnumDecl final : public NominalTypeDecl {
   SourceLoc EnumLoc;

   enum SemanticInfoFlags : uint8_t {
      // Is the raw type valid?
         HasComputedRawType         = 1 << 0,
      // Is the complete set of (auto-incremented) raw values available?
         HasFixedRawValues          = 1 << 1,
      // Is the complete set of raw values type checked?
         HasFixedRawValuesAndTypes  = 1 << 2,
   };

   struct {
      /// The raw type and a bit to indicate whether the
      /// raw was computed yet or not.
      llvm::PointerIntPair<Type, 3, OptionSet<SemanticInfoFlags>> RawTypeAndFlags;

      bool hasRawType() const {
         return RawTypeAndFlags.getInt().contains(HasComputedRawType);
      }
      void cacheRawType(Type ty) {
         auto flags = RawTypeAndFlags.getInt() | HasComputedRawType;
         RawTypeAndFlags.setPointerAndInt(ty, flags);
      }

      bool hasFixedRawValues() const {
         return RawTypeAndFlags.getInt().contains(HasFixedRawValues);
      }
      bool hasCheckedRawValues() const {
         return RawTypeAndFlags.getInt().contains(HasFixedRawValuesAndTypes);
      }
   } LazySemanticInfo;

   friend class EnumRawValuesRequest;
   friend class EnumRawTypeRequest;
   friend class TypeChecker;

public:
   EnumDecl(SourceLoc EnumLoc, Identifier Name, SourceLoc NameLoc,
            MutableArrayRef<TypeLoc> Inherited,
            GenericParamList *GenericParams, DeclContext *DC);

   SourceLoc getStartLoc() const { return EnumLoc; }
   SourceRange getSourceRange() const {
      return SourceRange(EnumLoc, getBraces().end);
   }

public:
   /// A range for iterating the elements of an enum.
   using ElementRange = DowncastFilterRange<EnumElementDecl, DeclRange>;

   /// A range for iterating the cases of an enum.
   using CaseRange = DowncastFilterRange<EnumCaseDecl, DeclRange>;

   /// Return a range that iterates over all the elements of an enum.
   ElementRange getAllElements() const {
      return ElementRange(getMembers());
   }

   unsigned getNumElements() const {
      auto eltRange = getAllElements();
      return std::distance(eltRange.begin(), eltRange.end());
   }

   /// If this enum has a unique element, return it. A unique element can
   /// either hold a value or not, and the existence of one unique element does
   /// not imply the existence or non-existence of the opposite unique element.
   EnumElementDecl *getUniqueElement(bool hasValue) const;

   /// Return a range that iterates over all the cases of an enum.
   CaseRange getAllCases() const {
      return CaseRange(getMembers());
   }

   /// Insert all of the 'case' element declarations into a DenseSet.
   void getAllElements(llvm::DenseSet<EnumElementDecl*> &elements) const {
      for (auto elt : getAllElements())
         elements.insert(elt);
   }

   /// Whether this enum has a raw value type that recursively references itself.
   bool hasCircularRawValue() const;

   /// Record that this enum has had all of its raw values computed.
   void setHasFixedRawValues();

   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Enum;
   }
   static bool classof(const GenericTypeDecl *D) {
      return D->getKind() == DeclKind::Enum;
   }
   static bool classof(const NominalTypeDecl *D) {
      return D->getKind() == DeclKind::Enum;
   }
   static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDecl())
         return classof(D);
      return false;
   }
   static bool classof(const IterableDeclContext *C) {
      auto NTD = dyn_cast<NominalTypeDecl>(C);
      return NTD && classof(NTD);
   }

   /// Determine whether this enum declares a raw type in its inheritance clause.
   bool hasRawType() const { return (bool)getRawType(); }

   /// Retrieve the declared raw type of the enum from its inheritance clause,
   /// or null if it has none.
   Type getRawType() const;

   /// Set the raw type of the enum from its inheritance clause.
   void setRawType(Type rawType) {
      auto flags = LazySemanticInfo.RawTypeAndFlags.getInt();
      LazySemanticInfo.RawTypeAndFlags.setPointerAndInt(
         rawType, flags | HasComputedRawType);
   }

   /// True if none of the enum cases have associated values.
   ///
   /// Note that this is true for enums with absolutely no cases.
   bool hasOnlyCasesWithoutAssociatedValues() const;

   /// True if any of the enum cases have availability annotations.
   ///
   /// Note that this is false for enums with absolutely no cases.
   bool hasPotentiallyUnavailableCaseValue() const;

   /// True if the enum has cases.
   bool hasCases() const {
      return !getAllElements().empty();
   }

   /// True if the enum is marked 'indirect'.
   bool isIndirect() const {
      return getAttrs().hasAttribute<IndirectAttr>();
   }

   /// True if the enum can be exhaustively switched within \p useDC.
   ///
   /// Note that this property is \e not necessarily true for all children of
   /// \p useDC. In particular, an inlinable function does not get to switch
   /// exhaustively over a non-exhaustive enum declared in the same module.
   ///
   /// This is the predicate used when deciding if a switch statement needs a
   /// default case. It should not be used for optimization or code generation.
   ///
   /// \sa isEffectivelyExhaustive
   bool isFormallyExhaustive(const DeclContext *useDC) const;

   /// True if the enum can be exhaustively switched within a function defined
   /// within \p M, with \p expansion specifying whether the function is
   /// inlinable.
   ///
   /// This is the predicate used when making optimization and code generation
   /// decisions. It should not be used at the AST or semantic level.
   ///
   /// \sa isFormallyExhaustive
   bool isEffectivelyExhaustive(ModuleDecl *M,
                                ResilienceExpansion expansion) const;
};

/// StructDecl - This is the declaration of a struct, for example:
///
///    struct Complex { var R : Double, I : Double }
///
/// The type of the decl itself is a MetatypeType; use getDeclaredType()
/// to get the declared type ("Complex" in the above example).
class StructDecl final : public NominalTypeDecl {
   SourceLoc StructLoc;

public:
   StructDecl(SourceLoc StructLoc, Identifier Name, SourceLoc NameLoc,
              MutableArrayRef<TypeLoc> Inherited,
              GenericParamList *GenericParams, DeclContext *DC);

   SourceLoc getStartLoc() const { return StructLoc; }
   SourceRange getSourceRange() const {
      return SourceRange(StructLoc, getBraces().end);
   }

   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Struct;
   }
   static bool classof(const GenericTypeDecl *D) {
      return D->getKind() == DeclKind::Struct;
   }
   static bool classof(const NominalTypeDecl *D) {
      return D->getKind() == DeclKind::Struct;
   }
   static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDecl())
         return classof(D);
      return false;
   }
   static bool classof(const IterableDeclContext *C) {
      auto NTD = dyn_cast<NominalTypeDecl>(C);
      return NTD && classof(NTD);
   }

   /// Does this struct contain unreferenceable storage, such as C fields that
   /// cannot be represented in Swift?
   bool hasUnreferenceableStorage() const {
      return Bits.StructDecl.HasUnreferenceableStorage;
   }

   void setHasUnreferenceableStorage(bool v) {
      Bits.StructDecl.HasUnreferenceableStorage = v;
   }
};

/// The kind of artificial main to generate for a class.
enum class ArtificialMainKind : uint8_t {
   NSApplicationMain,
   UIApplicationMain,
};

/// This is the base type for AncestryOptions. Each flag describes possible
/// interesting kinds of superclasses that a class may have.
enum class AncestryFlags : uint8_t {
   /// The class or one of its superclasses is @objc.
      ObjC = (1<<0),

   /// The class or one of its superclasses is @objcMembers.
      ObjCMembers = (1<<1),

   /// The class or one of its superclasses is generic.
      Generic = (1<<2),

   /// The class or one of its superclasses is resilient.
      Resilient = (1<<3),

   /// The class or one of its superclasses has resilient metadata and is in a
   /// different resilience domain.
      ResilientOther = (1<<4),

   /// The class or one of its superclasses is imported from Clang.
      ClangImported = (1<<5),

   /// The class or one of its superclasses requires stored property initializers.
      RequiresStoredPropertyInits = (1<<6),
};

/// Return type of ClassDecl::checkAncestry(). Describes a set of interesting
/// kinds of superclasses that a class may have.
using AncestryOptions = OptionSet<AncestryFlags>;

/// ClassDecl - This is the declaration of a class, for example:
///
///    class Complex { var R : Double, I : Double }
///
/// The type of the decl itself is a MetatypeType; use getDeclaredType()
/// to get the declared type ("Complex" in the above example).
class ClassDecl final : public NominalTypeDecl {
   class ObjCMethodLookupTable;

   SourceLoc ClassLoc;
   ObjCMethodLookupTable *ObjCMethodLookup = nullptr;

   /// Create the Objective-C member lookup table.
   void createObjCMethodLookup();

   struct {
      /// The superclass decl and a bit to indicate whether the
      /// superclass was computed yet or not.
      llvm::PointerIntPair<ClassDecl *, 1, bool> SuperclassDecl;

      /// The superclass type and a bit to indicate whether the
      /// superclass was computed yet or not.
      llvm::PointerIntPair<Type, 1, bool> SuperclassType;
   } LazySemanticInfo;

   bool hasForcedEmittedMembers() const {
      return Bits.ClassDecl.HasForcedEmittedMembers;
   }

   void setHasForcedEmittedMembers() {
      Bits.ClassDecl.HasForcedEmittedMembers = true;
   }

   Optional<bool> getCachedInheritsSuperclassInitializers() const {
      if (Bits.ClassDecl.ComputedInheritsSuperclassInits)
         return Bits.ClassDecl.InheritsSuperclassInits;

      return None;
   }

   /// Marks that this class inherits convenience initializers from its
   /// superclass.
   void setInheritsSuperclassInitializers(bool value) {
      Bits.ClassDecl.InheritsSuperclassInits = value;
      Bits.ClassDecl.ComputedInheritsSuperclassInits = true;
   }

   friend class SuperclassDeclRequest;
   friend class SuperclassTypeRequest;
   friend class EmittedMembersRequest;
   friend class InheritsSuperclassInitializersRequest;
   friend class TypeChecker;

public:
   ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc,
             MutableArrayRef<TypeLoc> Inherited,
             GenericParamList *GenericParams, DeclContext *DC);

   SourceLoc getStartLoc() const { return ClassLoc; }
   SourceRange getSourceRange() const {
      return SourceRange(ClassLoc, getBraces().end);
   }

   /// Determine whether the member area of this class's metadata (which consists
   /// of field offsets and vtable entries) is to be considered opaque by clients.
   ///
   /// Note that even @_fixed_layout classes have resilient metadata if they are
   /// in a resilient module.
   bool hasResilientMetadata() const;

   /// Determine whether this class has resilient metadata when accessed from the
   /// given module and resilience expansion.
   bool hasResilientMetadata(ModuleDecl *M, ResilienceExpansion expansion) const;

   /// Determine whether this class has a superclass.
   bool hasSuperclass() const { return (bool)getSuperclassDecl(); }

   /// Retrieve the superclass of this class, or null if there is no superclass.
   Type getSuperclass() const;

   /// Retrieve the ClassDecl for the superclass of this class, or null if there
   /// is no superclass.
   ClassDecl *getSuperclassDecl() const;

   /// Check if this class is a superclass or equal to the given class.
   bool isSuperclassOf(ClassDecl *other) const;

   /// Set the superclass of this class.
   void setSuperclass(Type superclass);

   /// Whether this class has a circular reference in its inheritance hierarchy.
   bool hasCircularInheritance() const;

   /// Walk this class and all of the superclasses of this class, transitively,
   /// invoking the callback function for each class.
   ///
   /// \param fn The callback function that will be invoked for each superclass.
   /// It can return \c Continue to continue the traversal. Returning
   /// \c SkipChildren halts the search and returns \c false, while returning
   /// \c Stop halts the search and returns \c true.
   ///
   /// \returns \c true if \c fn returned \c Stop for any class, \c false
   /// otherwise.
   bool walkSuperclasses(
      llvm::function_ref<TypeWalker::Action(ClassDecl *)> fn) const;

   //// Whether this class requires all of its stored properties to
   //// have initializers in the class definition.
   bool requiresStoredPropertyInits() const {
      return checkAncestry(AncestryFlags::RequiresStoredPropertyInits);
   }

   /// \see getForeignClassKind
   enum class ForeignKind : uint8_t {
      /// A normal Swift or Objective-C class.
         Normal = 0,
      /// An imported Core Foundation type. These are AnyObject-compatible but
      /// do not have runtime metadata.
         CFType,
      /// An imported Objective-C type whose class and metaclass symbols are not
      /// both available at link-time but can be accessed through the Objective-C
      /// runtime.
         RuntimeOnly
   };

   /// Whether this class is "foreign", meaning that it is implemented
   /// by a runtime that Swift does not have first-class integration
   /// with.  This generally means that:
   ///   - class data is either abstracted or cannot be made to
   ///     fit with Swift's metatype schema, and/or
   ///   - there is no facility for subclassing or adding polymorphic
   ///     methods to the class.
   ///
   /// We may find ourselves wanting to break this bit into more
   /// precise chunks later.
   ForeignKind getForeignClassKind() const {
      return static_cast<ForeignKind>(Bits.ClassDecl.RawForeignKind);
   }
   void setForeignClassKind(ForeignKind kind) {
      Bits.ClassDecl.RawForeignKind = static_cast<unsigned>(kind);
   }

   /// Returns true if this class is any kind of "foreign class".
   ///
   /// \see getForeignClassKind
   bool isForeign() const {
      return getForeignClassKind() != ForeignKind::Normal;
   }

   /// Returns true if the class has designated initializers that are not listed
   /// in its members.
   ///
   /// This can occur, for example, if the class is an Objective-C class with
   /// initializers that cannot be represented in Swift.
   bool hasMissingDesignatedInitializers() const;

   void setHasMissingDesignatedInitializers(bool newValue = true) {
      Bits.ClassDecl.ComputedHasMissingDesignatedInitializers = 1;
      Bits.ClassDecl.HasMissingDesignatedInitializers = newValue;
   }

   /// Returns true if the class has missing members that require vtable entries.
   ///
   /// In this case, the class cannot be subclassed, because we cannot construct
   /// the vtable for the subclass.
   bool hasMissingVTableEntries() const;

   void setHasMissingVTableEntries(bool newValue = true) {
      Bits.ClassDecl.ComputedHasMissingVTableEntries = 1;
      Bits.ClassDecl.HasMissingVTableEntries = newValue;
   }

   /// Returns true if this class cannot be used with weak or unowned
   /// references.
   ///
   /// Note that this is true if this class or any of its ancestor classes
   /// are marked incompatible.
   bool isIncompatibleWithWeakReferences() const;

   void setIsIncompatibleWithWeakReferences(bool newValue = true) {
      Bits.ClassDecl.IsIncompatibleWithWeakReferences = newValue;
   }

   /// Find a method of a class that overrides a given method.
   /// Return nullptr, if no such method exists.
   AbstractFunctionDecl *findOverridingDecl(
      const AbstractFunctionDecl *method) const;

   /// Find a method implementation which will be used when a given method
   /// is invoked on an instance of this class. This implementation may stem
   /// either from a class itself or its direct or indirect superclasses.
   AbstractFunctionDecl *findImplementingMethod(
      const AbstractFunctionDecl *method) const;

   /// Retrieve the destructor for this class.
   DestructorDecl *getDestructor() const;

   /// Determine whether this class inherits the convenience initializers
   /// from its superclass.
   bool inheritsSuperclassInitializers();

   /// Walks the class hierarchy starting from this class, checking various
   /// conditions.
   AncestryOptions checkAncestry() const;

   /// Check if the class has ancestry of the given kind.
   bool checkAncestry(AncestryFlags flag) const {
      return checkAncestry().contains(flag);
   }

   /// The type of metaclass to use for a class.
   enum class MetaclassKind : uint8_t {
      ObjC,
      SwiftStub,
   };

   /// Determine which sort of metaclass to use for this class
   MetaclassKind getMetaclassKind() const;

   /// Retrieve the name to use for this class when interoperating with
   /// the Objective-C runtime.
   StringRef getObjCRuntimeName(llvm::SmallVectorImpl<char> &buffer) const;

   /// Returns the appropriate kind of entry point to generate for this class,
   /// based on its attributes.
   ///
   /// It is an error to call this on a class that does not have a
   /// *ApplicationMain attribute.
   ArtificialMainKind getArtificialMainKind() const;

   using NominalTypeDecl::lookupDirect;

   /// Look in this class and its extensions (but not any of its Interfaces or
   /// superclasses) for declarations with a given Objective-C selector.
   ///
   /// Note that this can find methods, initializers, deinitializers,
   /// getters, and setters.
   ///
   /// \param selector The Objective-C selector of the method we're
   /// looking for.
   ///
   /// \param isInstance Whether we are looking for an instance method
   /// (vs. a class method).
//   MutableArrayRef<AbstractFunctionDecl *> lookupDirect(ObjCSelector selector,
//                                                        bool isInstance);

   /// Record the presence of an @objc method with the given selector.
//   void recordObjCMethod(AbstractFunctionDecl *method, ObjCSelector selector);

   /// Get all the members of this class, synthesizing any implicit members
   /// that appear in the vtable if needed.
   DeclRange getEmittedMembers() const;

   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Class;
   }
   static bool classof(const GenericTypeDecl *D) {
      return D->getKind() == DeclKind::Class;
   }
   static bool classof(const NominalTypeDecl *D) {
      return D->getKind() == DeclKind::Class;
   }
   static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDecl())
         return classof(D);
      return false;
   }
   static bool classof(const IterableDeclContext *C) {
      auto NTD = dyn_cast<NominalTypeDecl>(C);
      return NTD && classof(NTD);
   }

   /// Returns true if the decl uses the Objective-C generics model.
   ///
   /// This is true of imported Objective-C classes.
//   bool usesObjCGenericsModel() const {
//      return hasClangNode() && isGenericContext() && isObjC();
//   }

   /// True if the class is known to be implemented in Swift.
   bool hasKnownPolarphpImplementation() const {
      return !hasClangNode();
   }
};


/// Describes whether a requirement refers to 'Self', for use in the
/// is-inheritable and is-available-existential checks.
struct SelfReferenceKind {
   bool result;
   bool parameter;
   bool requirement;
   bool other;

   /// The type does not refer to 'Self' at all.
   static SelfReferenceKind None() {
      return SelfReferenceKind(false, false, false, false);
   }

   /// The type refers to 'Self', but only as the result type of a method.
   static SelfReferenceKind Result() {
      return SelfReferenceKind(true, false, false, false);
   }

   /// The type refers to 'Self', but only as the parameter type of a method.
   static SelfReferenceKind Parameter() {
      return SelfReferenceKind(false, true, false, false);
   }

   /// The type refers to 'Self' within a same-type requiement.
   static SelfReferenceKind Requirement() {
      return SelfReferenceKind(false, false, true, false);
   }

   /// The type refers to 'Self' in a position that is invariant.
   static SelfReferenceKind Other() {
      return SelfReferenceKind(false, false, false, true);
   }

   SelfReferenceKind flip() const {
      return SelfReferenceKind(parameter, result, requirement, other);
   }

   SelfReferenceKind operator|=(SelfReferenceKind kind) {
      result |= kind.result;
      requirement |= kind.requirement;
      parameter |= kind.parameter;
      other |= kind.other;
      return *this;
   }

   operator bool() const {
      return result || parameter || requirement || other;
   }

private:
   SelfReferenceKind(bool result, bool parameter, bool requirement, bool other)
      : result(result), parameter(parameter), requirement(requirement),
        other(other) { }
};

/// InterfaceDecl - A declaration of a Interface, for example:
///
///   Interface Drawable {
///     func draw()
///   }
///
/// Every Interface has an implicitly-created 'Self' generic parameter that
/// stands for a type that conforms to the Interface. For example,
///
///   Interface Cloneable {
///     func clone() -> Self
///   }
///
class InterfaceDecl final : public NominalTypeDecl {
   SourceLoc InterfaceLoc;

   ArrayRef<InterfaceDecl *> InheritedInterfaces;

   struct {
      /// The superclass decl and a bit to indicate whether the
      /// superclass was computed yet or not.
      llvm::PointerIntPair<ClassDecl *, 1, bool> SuperclassDecl;

      /// The superclass type and a bit to indicate whether the
      /// superclass was computed yet or not.
      llvm::PointerIntPair<Type, 1, bool> SuperclassType;
   } LazySemanticInfo;

   /// The generic signature representing exactly the new requirements introduced
   /// by this Interface.
   const Requirement *RequirementSignature = nullptr;

   /// Returns the cached result of \c requiresClass or \c None if it hasn't yet
   /// been computed.
   Optional<bool> getCachedRequiresClass() const {
      if (Bits.InterfaceDecl.RequiresClassValid)
         return Bits.InterfaceDecl.RequiresClass;

      return None;
   }

   /// Caches the result of \c requiresClass
   void setCachedRequiresClass(bool requiresClass) {
      Bits.InterfaceDecl.RequiresClassValid = true;
      Bits.InterfaceDecl.RequiresClass = requiresClass;
   }

   /// Returns the cached result of \c existentialConformsToSelf or \c None if it
   /// hasn't yet been computed.
   Optional<bool> getCachedExistentialConformsToSelf() const {
      if (Bits.InterfaceDecl.ExistentialConformsToSelfValid)
         return Bits.InterfaceDecl.ExistentialConformsToSelf;

      return None;
   }

   /// Caches the result of \c existentialConformsToSelf
   void setCachedExistentialConformsToSelf(bool result) {
      Bits.InterfaceDecl.ExistentialConformsToSelfValid = true;
      Bits.InterfaceDecl.ExistentialConformsToSelf = result;
   }

   /// Returns the cached result of \c existentialTypeSupported or \c None if it
   /// hasn't yet been computed.
   Optional<bool> getCachedExistentialTypeSupported() {
      if (Bits.InterfaceDecl.ExistentialTypeSupportedValid)
         return Bits.InterfaceDecl.ExistentialTypeSupported;

      return None;
   }

   /// Caches the result of \c existentialTypeSupported
   void setCachedExistentialTypeSupported(bool supported) {
      Bits.InterfaceDecl.ExistentialTypeSupportedValid = true;
      Bits.InterfaceDecl.ExistentialTypeSupported = supported;
   }

   ArrayRef<InterfaceDecl *> getInheritedInterfacesSlow();

   bool hasLazyRequirementSignature() const {
      return Bits.InterfaceDecl.HasLazyRequirementSignature;
   }

   friend class SuperclassDeclRequest;
   friend class SuperclassTypeRequest;
   friend class RequirementSignatureRequest;
   friend class InterfaceRequiresClassRequest;
   friend class ExistentialConformsToSelfRequest;
   friend class ExistentialTypeSupportedRequest;
   friend class TypeChecker;

public:
   InterfaceDecl(DeclContext *DC, SourceLoc InterfaceLoc, SourceLoc NameLoc,
                Identifier Name, MutableArrayRef<TypeLoc> Inherited,
                TrailingWhereClause *TrailingWhere);

   using Decl::getAstContext;

   /// Retrieve the set of Interfaces inherited from this Interface.
   ArrayRef<InterfaceDecl *> getInheritedInterfaces() const {
      if (Bits.InterfaceDecl.InheritedInterfacesValid)
         return InheritedInterfaces;

      return const_cast<InterfaceDecl *>(this)->getInheritedInterfacesSlow();
   }

   /// Determine whether this Interface has a superclass.
   bool hasSuperclass() const { return (bool)getSuperclassDecl(); }

   /// Retrieve the superclass of this Interface, or null if there is no superclass.
   Type getSuperclass() const;

   /// Retrieve the ClassDecl for the superclass of this Interface, or null if there
   /// is no superclass.
   ClassDecl *getSuperclassDecl() const;

   /// Set the superclass of this Interface.
   void setSuperclass(Type superclass);

   /// Retrieve the set of AssociatedTypeDecl members of this Interface; this
   /// saves loading the set of members in cases where there's no possibility of
   /// a Interface having nested types (ObjC Interfaces).
   llvm::TinyPtrVector<AssociatedTypeDecl *> getAssociatedTypeMembers() const;

   /// Returns a Interface requirement with the given name, or nullptr if the
   /// name has multiple overloads, or no overloads at all.
   ValueDecl *getSingleRequirement(DeclName name) const;

   /// Returns an associated type with the given name, or nullptr if one does
   /// not exist.
   AssociatedTypeDecl *getAssociatedType(Identifier name) const;

   /// Walk this Interface and all of the Interfaces inherited by this Interface,
   /// transitively, invoking the callback function for each Interface.
   ///
   /// \param fn The callback function that will be invoked for each inherited
   /// Interface. It can return \c Continue to continue the traversal,
   /// \c SkipChildren to avoid visiting the children of the given Interface
   /// but continue the search, and \c Stop to halt the search.
   ///
   /// \returns \c true if \c fn returned \c Stop for any Interface, \c false
   /// otherwise.
   bool walkInheritedInterfaces(
      llvm::function_ref<TypeWalker::Action(InterfaceDecl *)> fn) const;

   /// Determine whether this Interface inherits from the given ("super")
   /// Interface.
   bool inheritsFrom(const InterfaceDecl *Super) const;

   InterfaceType *getDeclaredType() const {
      return reinterpret_cast<InterfaceType *>(
         NominalTypeDecl::getDeclaredType().getPointer());
   }

   SourceLoc getStartLoc() const { return InterfaceLoc; }
   SourceRange getSourceRange() const {
      return SourceRange(InterfaceLoc, getBraces().end);
   }

   /// True if this Interface can only be conformed to by class types.
   bool requiresClass() const;

   /// Determine whether an existential conforming to this Interface can be
   /// matched with a generic type parameter constrained to this Interface.
   /// This is only permitted if there is nothing "non-trivial" that we
   /// can do with the metatype, which means the Interface must not have
   /// any static methods and must be declared @objc.
   bool existentialConformsToSelf() const;

   /// Does this Interface require a self-conformance witness table?
   bool requiresSelfConformanceWitnessTable() const;

   /// Find direct Self references within the given requirement.
   ///
   /// \param allowCovariantParameters If true, 'Self' is assumed to be
   /// covariant anywhere; otherwise, only in the return type of the top-level
   /// function type.
   ///
   /// \param skipAssocTypes If true, associated types of 'Self' are ignored;
   /// otherwise, they count as an 'other' usage of 'Self'.
   SelfReferenceKind findInterfaceSelfReferences(const ValueDecl *decl,
                                                bool allowCovariantParameters,
                                                bool skipAssocTypes) const;

   /// Determine whether we are allowed to refer to an existential type
   /// conforming to this Interface. This is only permitted if the type of
   /// the member does not contain any associated types, and does not
   /// contain 'Self' in 'parameter' or 'other' position.
   bool isAvailableInExistential(const ValueDecl *decl) const;

   /// Determine whether we are allowed to refer to an existential type
   /// conforming to this Interface. This is only permitted if the types of
   /// all the members do not contain any associated types, and do not
   /// contain 'Self' in 'parameter' or 'other' position.
   bool existentialTypeSupported() const;

private:
   void computeKnownInterfaceKind() const;

public:
   /// If this is known to be a compiler-known Interface, returns the kind.
   /// Otherwise returns None.
   Optional<KnownInterfaceKind> getKnownInterfaceKind() const {
      if (Bits.InterfaceDecl.KnownInterface == 0)
         computeKnownInterfaceKind();

      if (Bits.InterfaceDecl.KnownInterface == 1)
         return None;

      return static_cast<KnownInterfaceKind>(Bits.InterfaceDecl.KnownInterface - 2);
   }

   /// Check whether this Interface is of a specific, known Interface kind.
   bool isSpecificInterface(KnownInterfaceKind kind) const {
      if (auto knownKind = getKnownInterfaceKind())
         return *knownKind == kind;

      return false;
   }

   /// Whether this Interface has a circular reference in its list of inherited
   /// Interfaces.
   bool hasCircularInheritedInterfaces() const;

   /// Returns true if the Interface has requirements that are not listed in its
   /// members.
   ///
   /// This can occur, for example, if the Interface is an Objective-C Interface
   /// with requirements that cannot be represented in Swift.
   bool hasMissingRequirements() const {
      (void)getMembers();
      return Bits.InterfaceDecl.HasMissingRequirements;
   }

   void setHasMissingRequirements(bool newValue) {
      Bits.InterfaceDecl.HasMissingRequirements = newValue;
   }

   /// Returns the default type witness for an associated type, or a null
   /// type if there is no default.
   Type getDefaultTypeWitness(AssociatedTypeDecl *assocType) const;

   /// Set the default type witness for an associated type.
   void setDefaultTypeWitness(AssociatedTypeDecl *assocType, Type witness);

   /// Returns the default witness for a requirement, or nullptr if there is
   /// no default.
   Witness getDefaultWitness(ValueDecl *requirement) const;

   /// Record the default witness for a requirement.
   void setDefaultWitness(ValueDecl *requirement, Witness witness);

   /// Returns the default associated conformance witness for an associated
   /// type, or \c None if there is no default.
   InterfaceConformanceRef
   getDefaultAssociatedConformanceWitness(CanType association,
                                          InterfaceDecl *requirement) const;

   /// Set the default associated conformance witness for the given
   /// associated conformance.
   void setDefaultAssociatedConformanceWitness(
      CanType association,
      InterfaceDecl *requirement,
      InterfaceConformanceRef conformance);

   /// Retrieve the name to use for this Interface when interoperating
   /// with the Objective-C runtime.
   StringRef getObjCRuntimeName(llvm::SmallVectorImpl<char> &buffer) const;

   /// Retrieve the requirements that describe this Interface.
   ///
   /// These are the requirements including any inherited Interfaces
   /// and conformances for associated types that are introduced in this
   /// Interface. Requirements implied via any other Interface (e.g., inherited
   /// Interfaces of the inherited Interfaces) are not mentioned. The conformance
   /// requirements listed here become entries in the witness table.
   ArrayRef<Requirement> getRequirementSignature() const;

   /// Is the requirement signature currently being computed?
   bool isComputingRequirementSignature() const;

   /// Has the requirement signature been computed yet?
   bool isRequirementSignatureComputed() const {
      return RequirementSignature != nullptr;
   }

   void setRequirementSignature(ArrayRef<Requirement> requirements);

   void setLazyRequirementSignature(LazyMemberLoader *lazyLoader,
                                    uint64_t requirementSignatureData);

private:
   ArrayRef<Requirement> getCachedRequirementSignature() const;

public:
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Interface;
   }
   static bool classof(const GenericTypeDecl *D) {
      return D->getKind() == DeclKind::Interface;
   }
   static bool classof(const NominalTypeDecl *D) {
      return D->getKind() == DeclKind::Interface;
   }
   static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDecl())
         return classof(D);
      return false;
   }
   static bool classof(const IterableDeclContext *C) {
      auto NTD = dyn_cast<NominalTypeDecl>(C);
      return NTD && classof(NTD);
   }
};

/// AbstractStorageDecl - This is the common superclass for VarDecl and
/// SubscriptDecl, representing potentially settable memory locations.
class AbstractStorageDecl : public ValueDecl {
   friend class SetterAccessLevelRequest;
   friend class IsGetterMutatingRequest;
   friend class IsSetterMutatingRequest;
   friend class OpaqueReadOwnershipRequest;
   friend class StorageImplInfoRequest;
   friend class RequiresOpaqueAccessorsRequest;
   friend class RequiresOpaqueModifyCoroutineRequest;
   friend class SynthesizeAccessorRequest;

public:
   static const size_t MaxNumAccessors = 255;
private:
   /// A record of the accessors for the declaration.
   class alignas(1 << 3) AccessorRecord final :
      private llvm::TrailingObjects<AccessorRecord, AccessorDecl*> {
      friend TrailingObjects;

      using AccessorIndex = uint8_t;
      static const AccessorIndex InvalidIndex = 0;

      /// The range of the braces around the accessor clause.
      SourceRange Braces;

      /// The number of accessors currently stored in this record.
      AccessorIndex NumAccessors;

      /// The storage capacity of this record for accessors.  Always includes
      /// enough space for adding opaque accessors to the record, which are the
      /// only accessors that should ever be added retroactively; hence this
      /// field is only here for the purposes of safety checks.
      AccessorIndex AccessorsCapacity;

      /// Either 0, meaning there is no registered accessor of the given kind,
      /// or the index+1 of the accessor in the accessors array.
      AccessorIndex AccessorIndices[NumAccessorKinds];

      AccessorRecord(SourceRange braces,
                     ArrayRef<AccessorDecl*> accessors,
                     AccessorIndex accessorsCapacity);
   public:
      static AccessorRecord *create(AstContext &ctx, SourceRange braces,
                                    ArrayRef<AccessorDecl*> accessors);

      SourceRange getBracesRange() const { return Braces; }

      inline AccessorDecl *getAccessor(AccessorKind kind) const;

      ArrayRef<AccessorDecl *> getAllAccessors() const {
         return { getTrailingObjects<AccessorDecl*>(), NumAccessors };
      }

      void addOpaqueAccessor(AccessorDecl *accessor);

   private:
      MutableArrayRef<AccessorDecl *> getAccessorsBuffer() {
         return { getTrailingObjects<AccessorDecl*>(), NumAccessors };
      }

      bool registerAccessor(AccessorDecl *accessor, AccessorIndex index);
   };

   llvm::PointerIntPair<AccessorRecord*, 3, OptionalEnum<AccessLevel>> Accessors;

   struct {
      unsigned IsGetterMutatingComputed : 1;
      unsigned IsGetterMutating : 1;
      unsigned IsSetterMutatingComputed : 1;
      unsigned IsSetterMutating : 1;
      unsigned OpaqueReadOwnershipComputed : 1;
      unsigned OpaqueReadOwnership : 2;
      unsigned ImplInfoComputed : 1;
      unsigned RequiresOpaqueAccessorsComputed : 1;
      unsigned RequiresOpaqueAccessors : 1;
      unsigned RequiresOpaqueModifyCoroutineComputed : 1;
      unsigned RequiresOpaqueModifyCoroutine : 1;
   } LazySemanticInfo = { };

   /// The implementation info for the accessors.
   StorageImplInfo ImplInfo;

   /// Add a synthesized accessor.
   void setSynthesizedAccessor(AccessorKind kind, AccessorDecl *getter);

protected:
   AbstractStorageDecl(DeclKind Kind, bool IsStatic, DeclContext *DC,
                       DeclName Name, SourceLoc NameLoc,
                       StorageIsMutable_t supportsMutation)
      : ValueDecl(Kind, DC, Name, NameLoc),
        ImplInfo(StorageImplInfo::getSimpleStored(supportsMutation)) {
      Bits.AbstractStorageDecl.IsStatic = IsStatic;
   }

public:

   /// Should this declaration be treated as if annotated with transparent
   /// attribute.
   bool isTransparent() const;

   /// Is this a type ('static') variable?
   bool isStatic() const {
      return Bits.AbstractStorageDecl.IsStatic;
   }
   void setStatic(bool IsStatic) {
      Bits.AbstractStorageDecl.IsStatic = IsStatic;
   }

   /// \returns the way 'static'/'class' should be spelled for this declaration.
   StaticSpellingKind getCorrectStaticSpelling() const;

   /// Return the interface type of the stored value.
   Type getValueInterfaceType() const;

   /// Determine how this storage is implemented.
   StorageImplInfo getImplInfo() const;

   /// Overwrite the registered implementation-info.  This should be
   /// used carefully.
   void setImplInfo(StorageImplInfo implInfo) {
      LazySemanticInfo.ImplInfoComputed = 1;
      ImplInfo = implInfo;
   }

   ReadImplKind getReadImpl() const {
      return getImplInfo().getReadImpl();
   }
   WriteImplKind getWriteImpl() const {
      return getImplInfo().getWriteImpl();
   }
   ReadWriteImplKind getReadWriteImpl() const {
      return getImplInfo().getReadWriteImpl();
   }


   /// Return true if this is a VarDecl that has storage associated with
   /// it.
   bool hasStorage() const {
      return getImplInfo().hasStorage();
   }

   /// Return true if this storage has the basic accessors/capability
   /// to be mutated.  This is generally constant after the accessors are
   /// installed by the parser/importer/whatever.
   ///
   /// Note that this is different from the mutability of the declaration
   /// in the user language: sometimes we can assign to declarations that
   /// don't support mutation (e.g. to initialize them), and sometimes we
   /// can't mutate things that do support mutation (e.g. because their
   /// setter is private).
   StorageIsMutable_t supportsMutation() const {
      return getImplInfo().supportsMutation();
   }

   /// isSettable - Determine whether references to this decl may appear
   /// on the left-hand side of an assignment or as the operand of a
   /// `&` or 'inout' operator.
   bool isSettable(const DeclContext *UseDC,
                   const DeclRefExpr *base = nullptr) const;

   /// Does this storage declaration have explicitly-defined accessors
   /// written in the source?
   bool hasParsedAccessors() const;

   /// Return the ownership of values opaquely read from this storage.
   OpaqueReadOwnership getOpaqueReadOwnership() const;
   void setOpaqueReadOwnership(OpaqueReadOwnership ownership) {
      LazySemanticInfo.OpaqueReadOwnership = unsigned(ownership);
      LazySemanticInfo.OpaqueReadOwnershipComputed = true;
   }

   /// Return true if reading this storage requires the ability to
   /// modify the base value.
   bool isGetterMutating() const;
   void setIsGetterMutating(bool isMutating) {
      LazySemanticInfo.IsGetterMutating = isMutating;
      LazySemanticInfo.IsGetterMutatingComputed = true;
   }

   /// Return true if modifying this storage requires the ability to
   /// modify the base value.
   bool isSetterMutating() const;
   void setIsSetterMutating(bool isMutating) {
      LazySemanticInfo.IsSetterMutating = isMutating;
      LazySemanticInfo.IsSetterMutatingComputed = true;
   }

   AccessorDecl *getAccessor(AccessorKind kind) const {
      if (auto info = Accessors.getPointer())
         return info->getAccessor(kind);
      return nullptr;
   }

   ArrayRef<AccessorDecl*> getAllAccessors() const {
      if (const auto *info = Accessors.getPointer())
         return info->getAllAccessors();
      return {};
   }

   /// Return an accessor that this storage is expected to have, synthesizing
   /// one if necessary. Note that will always synthesize one, even if the
   /// accessor is not part of the expected opaque set for the storage, so use
   /// with caution.
   AccessorDecl *getSynthesizedAccessor(AccessorKind kind) const;

   /// Return an accessor part of the set of opaque accessors dictated by the
   /// requirements of the ABI.
   ///
   /// This will synthesize the accessor if one is required but not specified
   /// in source; for example, most of the time a mutable property is required
   /// to have a 'modify' accessor, but if the property was only written with
   /// 'get' and 'set' accessors, 'modify' will be synthesized to call 'get'
   /// followed by 'set'.
   ///
   /// If the accessor is not needed for ABI reasons, this returns nullptr.
   /// To ensure an accessor is always returned, use getSynthesizedAccessor().
   AccessorDecl *getOpaqueAccessor(AccessorKind kind) const;

   /// Return an accessor that was written in source. Returns null if the
   /// accessor was not explicitly defined by the user.
   AccessorDecl *getParsedAccessor(AccessorKind kind) const;

   /// Visit all parsed accessors.
   void visitParsedAccessors(llvm::function_ref<void (AccessorDecl*)>) const;

   /// Visit all opaque accessor kinds.
   void visitExpectedOpaqueAccessors(
      llvm::function_ref<void (AccessorKind)>) const;

   /// Visit all opaque accessors.
   void visitOpaqueAccessors(llvm::function_ref<void (AccessorDecl*)>) const;

   /// Visit all eagerly emitted accessors.
   ///
   /// This is the union of the parsed and opaque sets.
   void visitEmittedAccessors(llvm::function_ref<void (AccessorDecl*)>) const;

   void setAccessors(SourceLoc lbraceLoc, ArrayRef<AccessorDecl*> accessors,
                     SourceLoc rbraceLoc);

   /// Add a setter to an existing Computed var.
   ///
   /// This should only be used by the ClangImporter.
   void setComputedSetter(AccessorDecl *Set);

   /// Does this storage require opaque accessors of any kind?
   bool requiresOpaqueAccessors() const;

   /// Does this storage require an opaque accessor of the given kind?
   bool requiresOpaqueAccessor(AccessorKind kind) const;

   /// Does this storage require a 'get' accessor in its opaque-accessors set?
   bool requiresOpaqueGetter() const {
      return getOpaqueReadOwnership() != OpaqueReadOwnership::Borrowed;
   }

   /// Does this storage require a 'read' accessor in its opaque-accessors set?
   bool requiresOpaqueReadCoroutine() const {
      return getOpaqueReadOwnership() != OpaqueReadOwnership::Owned;
   }

   /// Does this storage require a 'set' accessor in its opaque-accessors set?
   bool requiresOpaqueSetter() const { return supportsMutation(); }

   /// Does this storage require a 'modify' accessor in its opaque-accessors set?
   bool requiresOpaqueModifyCoroutine() const;

   SourceRange getBracesRange() const {
      if (auto info = Accessors.getPointer())
         return info->getBracesRange();
      return SourceRange();
   }

   AccessLevel getSetterFormalAccess() const;

   AccessScope
   getSetterFormalAccessScope(const DeclContext *useDC = nullptr,
                              bool treatUsableFromInlineAsPublic = false) const;

   void setSetterAccess(AccessLevel accessLevel) {
      assert(!Accessors.getInt().hasValue());
      overwriteSetterAccess(accessLevel);
   }

   void overwriteSetterAccess(AccessLevel accessLevel);

   /// Given that this is an Objective-C property or subscript declaration,
   /// produce its getter selector.
//   ObjCSelector
//   getObjCGetterSelector(Identifier preferredName = Identifier()) const;

   /// Given that this is an Objective-C property or subscript declaration,
   /// produce its setter selector.
//   ObjCSelector
//   getObjCSetterSelector(Identifier preferredName = Identifier()) const;

   AbstractStorageDecl *getOverriddenDecl() const {
      return cast_or_null<AbstractStorageDecl>(ValueDecl::getOverriddenDecl());
   }

   /// Returns the location of 'override' keyword, if any.
   SourceLoc getOverrideLoc() const;

   /// Returns true if this declaration has a setter accessible from the given
   /// context.
   ///
   /// If \p DC is null, returns true only if the setter is public.
   ///
   /// See \c isAccessibleFrom for a discussion of the \p forConformance
   /// parameter.
   bool isSetterAccessibleFrom(const DeclContext *DC,
                               bool forConformance=false) const;

   /// Determine how this storage declaration should actually be accessed.
   AccessStrategy getAccessStrategy(AccessSemantics semantics,
                                    AccessKind accessKind,
                                    ModuleDecl *module,
                                    ResilienceExpansion expansion) const;

   /// Should this declaration behave as if it must be accessed
   /// resiliently, even when we're building a non-resilient module?
   ///
   /// This is used for diagnostics, because we do not want a behavior
   /// change between builds with resilience enabled and disabled.
   bool isFormallyResilient() const;

   /// Do we need to use resilient access patterns outside of this
   /// property's resilience domain?
   bool isResilient() const;

   /// Do we need to use resilient access patterns when accessing this
   /// property from the given module?
   bool isResilient(ModuleDecl *M, ResilienceExpansion expansion) const;

   /// True if the storage can be referenced by a keypath directly.
   /// Otherwise, its override must be referenced.
   bool isValidKeyPathComponent() const;

   /// True if the storage exports a property descriptor for key paths in
   /// other modules.
   bool exportsPropertyDescriptor() const;

   /// True if any of the accessors to the storage is private or fileprivate.
   bool hasPrivateAccessor() const;

   bool hasDidSetOrWillSetDynamicReplacement() const;

   bool hasAnyNativeDynamicAccessors() const;

   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
      return D->getKind() >= DeclKind::First_AbstractStorageDecl &&
             D->getKind() <= DeclKind::Last_AbstractStorageDecl;
   }
};

/// Describes which synthesized property for a property with an attached
/// wrapper is being referenced.
enum class PropertyWrapperSynthesizedPropertyKind {
   /// The backing storage property, which is a stored property of the
   /// wrapper type.
      Backing,
   /// A storage wrapper (e.g., `$foo`), which is a wrapper over the
   /// wrapper instance's `projectedValue` property.
      StorageWrapper,
};

/// VarDecl - 'var' and 'let' declarations.
class VarDecl : public AbstractStorageDecl {
   friend class NamingPatternRequest;
   NamedPattern *NamingPattern = nullptr;

public:
   enum class Introducer : uint8_t {
      Let = 0,
      Var = 1
   };

protected:
   PointerUnion<PatternBindingDecl *, Stmt *, VarDecl *> Parent;

   VarDecl(DeclKind kind, bool isStatic, Introducer introducer,
           bool issCaptureList, SourceLoc nameLoc, Identifier name,
           DeclContext *dc, StorageIsMutable_t supportsMutation);

public:
   VarDecl(bool isStatic, Introducer introducer, bool isCaptureList,
           SourceLoc nameLoc, Identifier name, DeclContext *dc)
      : VarDecl(DeclKind::Var, isStatic, introducer, isCaptureList, nameLoc,
                name, dc, StorageIsMutable_t(introducer == Introducer::Var)) {}

   SourceRange getSourceRange() const;

   Identifier getName() const { return getFullName().getBaseIdentifier(); }

   /// Returns the string for the base name, or "_" if this is unnamed.
   StringRef getNameStr() const {
      assert(!getFullName().isSpecial() && "Cannot get string for special names");
      return hasName() ? getBaseName().getIdentifier().str() : "_";
   }

   /// Get the type of the variable within its context. If the context is generic,
   /// this will use archetypes.
   Type getType() const;

   /// Retrieve the source range of the variable type, or an invalid range if the
   /// variable's type is not explicitly written in the source.
   ///
   /// Only for use in diagnostics.  It is not always possible to always
   /// precisely point to the variable type because of type aliases.
   SourceRange getTypeSourceRangeForDiagnostics() const;

   /// Returns whether the var is settable in the specified context: this
   /// is either because it is a stored var, because it has a custom setter, or
   /// is a let member in an initializer.
   ///
   /// Pass a null context and null base to check if it's always settable.
   bool isSettable(const DeclContext *UseDC,
                   const DeclRefExpr *base = nullptr) const;

   /// Return the parent pattern binding that may provide an initializer for this
   /// VarDecl.  This returns null if there is none associated with the VarDecl.
   PatternBindingDecl *getParentPatternBinding() const {
      if (!Parent)
         return nullptr;
      return Parent.dyn_cast<PatternBindingDecl *>();
   }
   void setParentPatternBinding(PatternBindingDecl *PBD) {
      assert(PBD);
      Parent = PBD;
   }

   /// Return the Pattern involved in initializing this VarDecl.  However, recall
   /// that the Pattern may be involved in initializing more than just this one
   /// vardecl.  For example, if this is a VarDecl for "x", the pattern may be
   /// "(x, y)" and the initializer on the PatternBindingDecl may be "(1,2)" or
   /// "foo()".
   ///
   /// If this has no parent pattern binding decl or statement associated, it
   /// returns null.
   ///
   Pattern *getParentPattern() const;

   /// Returns the parsed type of this variable declaration.  For parameters, this
   /// is the parsed type the user explicitly wrote.  For variables, this is the
   /// type the user wrote in the typed pattern that binds this variable.
   ///
   /// Note that there are many cases where the user may elide types.  This will
   /// return null in those cases.
   TypeRepr *getTypeReprOrParentPatternTypeRepr() const;

   /// Return the statement that owns the pattern associated with this VarDecl,
   /// if one exists.
   ///
   /// NOTE: After parsing and before type checking, all VarDecls from
   /// CaseLabelItem's Patterns return their CaseStmt. After type checking, we
   /// will have constructed the CaseLabelItem VarDecl linked list implying this
   /// will return nullptr. After type checking, if one wishes to find a parent
   /// pattern of a VarDecl of a CaseStmt, \see getRecursiveParentPatternStmt
   /// instead.
   Stmt *getParentPatternStmt() const {
      if (!Parent)
         return nullptr;
      return Parent.dyn_cast<Stmt *>();
   }

   void setParentPatternStmt(Stmt *s) {
      assert(s);
      Parent = s;
   }

   /// Look for the parent pattern stmt of this var decl, recursively
   /// looking through var decl pointers and then through any
   /// fallthroughts.
   Stmt *getRecursiveParentPatternStmt() const;

   /// Returns the var decl that this var decl is an implicit reference to if
   /// such a var decl exists.
   VarDecl *getParentVarDecl() const {
      if (!Parent)
         return nullptr;
      return Parent.dyn_cast<VarDecl *>();
   }

   /// Set \p v to be the pattern produced VarDecl that is the parent of this
   /// var decl.
   void setParentVarDecl(VarDecl *v) {
      assert(v && v != this);
      Parent = v;
   }

   NamedPattern *getNamingPattern() const;
   void setNamingPattern(NamedPattern *Pat);

   /// If this is a VarDecl that does not belong to a CaseLabelItem's pattern,
   /// return this. Otherwise, this VarDecl must belong to a CaseStmt's
   /// CaseLabelItem. In that case, return the first case label item of the first
   /// case stmt in a sequence of case stmts that fallthrough into each other.
   ///
   /// NOTE: During type checking, we emit an error if we have a single case
   /// label item with a pattern that has multiple var decls of the same
   /// name. This means that during type checking and before type checking, we
   /// may have a _malformed_ switch stmt var decl linked list since var decls in
   /// the same case label item that have the same name will point at the same
   /// canonical var decl, namely the first var decl with the name in the
   /// canonical case label item's var decl list. This is ok, since we are going
   /// to emit the error, but it requires us to be more careful/cautious before
   /// type checking has been complete when relying on canonical var decls
   /// matching up.
   VarDecl *getCanonicalVarDecl() const;

   /// If this is a case stmt var decl, return the var decl that corresponds to
   /// this var decl in the first case label item of the case stmt. Returns
   /// nullptr if this isn't a VarDecl that is part of a case stmt.
   NullablePtr<VarDecl> getCorrespondingFirstCaseLabelItemVarDecl() const;

   /// If this is a case stmt var decl, return the case body var decl that this
   /// var decl maps to.
   NullablePtr<VarDecl> getCorrespondingCaseBodyVariable() const;

   /// Return true if this var decl is an implicit var decl belonging to a case
   /// stmt's body.
   bool isCaseBodyVariable() const;

   /// True if the global stored property requires lazy initialization.
   bool isLazilyInitializedGlobal() const;

   /// Return the initializer involved in this VarDecl.  Recall that the
   /// initializer may be involved in initializing more than just this one
   /// vardecl though.  For example, if this is a VarDecl for "x", the pattern
   /// may be "(x, y)" and the initializer on the PatternBindingDecl may be
   /// "(1,2)" or "foo()".
   ///
   /// If this has no parent pattern binding decl associated, or if that pattern
   /// binding has no initial value, this returns null.
   ///
   Expr *getParentInitializer() const {
      if (auto *PBD = getParentPatternBinding()) {
         const auto i = PBD->getPatternEntryIndexForVarDecl(this);
         return PBD->getInit(i);
      }
      return nullptr;
   }

   /// Whether there exists an initializer for this \c VarDecl.
   bool isParentInitialized() const {
      if (auto *PBD = getParentPatternBinding()) {
         const auto i = PBD->getPatternEntryIndexForVarDecl(this);
         return PBD->isInitialized(i);
      }
      return false;
   }

   // Return whether this VarDecl has an initial value, either by checking
   // if it has an initializer in its parent pattern binding or if it has
   // the @_hasInitialValue attribute.
   bool hasInitialValue() const {
      return getAttrs().hasAttribute<HasInitialValueAttr>() ||
             isParentInitialized();
   }

   VarDecl *getOverriddenDecl() const {
      return cast_or_null<VarDecl>(AbstractStorageDecl::getOverriddenDecl());
   }

   /// Is this an immutable 'let' property?
   ///
   /// If this is a ParamDecl, isLet() is true iff
   /// getSpecifier() == Specifier::Default.
   bool isLet() const { return getIntroducer() == Introducer::Let; }

   Introducer getIntroducer() const {
      return Introducer(Bits.VarDecl.Introducer);
   }

   void setIntroducer(Introducer value) {
      Bits.VarDecl.Introducer = uint8_t(value);
   }

   /// Is this an element in a capture list?
   bool isCaptureList() const { return Bits.VarDecl.IsCaptureList; }

   /// Return true if this vardecl has an initial value bound to it in a way
   /// that isn't represented in the AST with an initializer in the pattern
   /// binding.  This happens in cases like "for i in ...", switch cases, etc.
   bool hasNonPatternBindingInit() const {
      return Bits.VarDecl.HasNonPatternBindingInit;
   }
   void setHasNonPatternBindingInit(bool V = true) {
      Bits.VarDecl.HasNonPatternBindingInit = V;
   }

   /// Determines if this var has an initializer expression that should be
   /// exposed to clients.
   /// There's a very narrow case when we would: if the decl is an instance
   /// member with an initializer expression and the parent type is
   /// @frozen and resides in a resilient module.
   bool isInitExposedToClients() const;

   /// Is this a special debugger variable?
   bool isDebuggerVar() const { return Bits.VarDecl.IsDebuggerVar; }
   void setDebuggerVar(bool IsDebuggerVar) {
      Bits.VarDecl.IsDebuggerVar = IsDebuggerVar;
   }

   /// Is this the synthesized storage for a 'lazy' property?
   bool isLazyStorageProperty() const {
      return Bits.VarDecl.IsLazyStorageProperty;
   }
   void setLazyStorageProperty(bool IsLazyStorage) {
      Bits.VarDecl.IsLazyStorageProperty = IsLazyStorage;
   }

   /// Retrieve the custom attributes that attach property wrappers to this
   /// property. The returned list contains all of the attached property wrapper attributes in source order,
   /// which means the outermost wrapper attribute is provided first.
   llvm::TinyPtrVector<CustomAttr *> getAttachedPropertyWrappers() const;

   /// Whether this property has any attached property wrappers.
   bool hasAttachedPropertyWrapper() const;

   /// Whether all of the attached property wrappers have an init(initialValue:) initializer.
   bool allAttachedPropertyWrappersHaveInitialValueInit() const;

   /// Retrieve the type of the attached property wrapper as a contextual
   /// type.
   ///
   /// \param index Which property wrapper type is being computed, where 0
   /// indicates the first (outermost) attached property wrapper.
   ///
   /// \returns a NULL type for properties without attached wrappers,
   /// an error type when the property wrapper type itself is erroneous,
   /// or the wrapper type itself, which may involve unbound generic
   /// types.
   Type getAttachedPropertyWrapperType(unsigned index) const;

   /// Retrieve information about the attached property wrapper type.
   ///
   /// \param i Which attached property wrapper type is being queried, where 0 is the outermost (first)
   /// attached property wrapper type.
   PropertyWrapperTypeInfo getAttachedPropertyWrapperTypeInfo(unsigned i) const;

   /// Retrieve the fully resolved attached property wrapper type.
   ///
   /// This type will be the fully-resolved form of
   /// \c getAttachedPropertyWrapperType(0), which will not contain any
   /// unbound generic types. It will be the type of the backing property.
   Type getPropertyWrapperBackingPropertyType() const;

   /// Retrieve information about the backing properties of the attached
   /// property wrapper.
   PropertyWrapperBackingPropertyInfo
   getPropertyWrapperBackingPropertyInfo() const;

   /// Retrieve information about the mutability of the composed
   /// property wrappers.
   Optional<PropertyWrapperMutability>
   getPropertyWrapperMutability() const;

   /// Retrieve the backing storage property for a property that has an
   /// attached property wrapper.
   ///
   /// The backing storage property will be a stored property of the
   /// wrapper's type. This will be equivalent to
   /// \c getAttachedPropertyWrapperType(0) when it is fully-specified;
   /// if \c getAttachedPropertyWrapperType(0) involves an unbound
   /// generic type, the backing storage property will be the appropriate
   /// bound generic version.
   VarDecl *getPropertyWrapperBackingProperty() const;

   /// Retreive the storage wrapper for a property that has an attached
   /// property wrapper.
   VarDecl *getPropertyWrapperStorageWrapper() const;

   /// Retrieve the backing storage property for a lazy property.
   VarDecl *getLazyStorageProperty() const;

   /// Whether this is a property with a property wrapper that was initialized
   /// via a value of the original type, e.g.,
   ///
   /// \code
   /// @Lazy var i = 17
   /// \end
   bool isPropertyWrapperInitializedWithInitialValue() const;

   /// Whether the memberwise initializer parameter for a property with a property wrapper type
   /// uses the wrapped type.
   bool isPropertyMemberwiseInitializedWithWrappedType() const;

   /// If this property is the backing storage for a property with an attached
   /// property wrapper, return the original property.
   ///
   /// \param kind If not \c None, only returns the original property when
   /// \c this property is the specified synthesized property.
   VarDecl *getOriginalWrappedProperty(
      Optional<PropertyWrapperSynthesizedPropertyKind> kind = None) const;

   /// Set the property that wraps to this property as it's backing
   /// property.
   void setOriginalWrappedProperty(VarDecl *originalProperty);

   /// Return the Objective-C runtime name for this property.
//   Identifier getObjCPropertyName() const;

   /// Retrieve the default Objective-C selector for the getter of a
   /// property of the given name.
//   static ObjCSelector getDefaultObjCGetterSelector(AstContext &ctx,
//                                                    Identifier propertyName);

   /// Retrieve the default Objective-C selector for the setter of a
   /// property of the given name.
//   static ObjCSelector getDefaultObjCSetterSelector(AstContext &ctx,
//                                                    Identifier propertyName);

   /// If this is a simple 'let' constant, emit a note with a fixit indicating
   /// that it can be rewritten to a 'var'.  This is used in situations where the
   /// compiler detects obvious attempts to mutate a constant.
   void emitLetToVarNoteIfSimple(DeclContext *UseDC) const;

   /// Returns true if the name is the self identifier and is implicit.
   bool isSelfParameter() const;

   /// Determine whether this property will be part of the implicit memberwise
   /// initializer.
   ///
   /// \param preferDeclaredProperties When encountering a `lazy` property
   /// or a property that has an attached property wrapper, prefer the
   /// actual declared property (which may or may not be considered "stored"
   /// as the moment) to the backing storage property. Otherwise, the stored
   /// backing property will be treated as the member-initialized property.
   bool isMemberwiseInitialized(bool preferDeclaredProperties) const;

   /// Return the range of semantics attributes attached to this VarDecl.
   auto getSemanticsAttrs() const
   -> decltype(getAttrs().getAttributes<SemanticsAttr>()) {
      return getAttrs().getAttributes<SemanticsAttr>();
   }

   /// Returns true if this VarDelc has the string \p attrValue as a semantics
   /// attribute.
   bool hasSemanticsAttr(StringRef attrValue) const {
      return llvm::any_of(getSemanticsAttrs(), [&](const SemanticsAttr *attr) {
         return attrValue.equals(attr->Value);
      });
   }

   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Var || D->getKind() == DeclKind::Param;
   }
};

enum class ParamSpecifier : uint8_t {
   Default = 0,
   InOut = 1,
   Shared = 2,
   Owned = 3,
};

/// A function parameter declaration.
class ParamDecl : public VarDecl {
   friend class DefaultArgumentInitContextRequest;
   friend class DefaultArgumentExprRequest;

   llvm::PointerIntPair<Identifier, 1, bool> ArgumentNameAndDestructured;
   SourceLoc ParameterNameLoc;
   SourceLoc ArgumentNameLoc;
   SourceLoc SpecifierLoc;

   TypeRepr *TyRepr = nullptr;

   struct StoredDefaultArgument {
      PointerUnion<Expr *, VarDecl *> DefaultArg;

      /// Stores the context for the default argument as well as a bit to
      /// indicate whether the default expression has been type-checked.
      llvm::PointerIntPair<Initializer *, 1, bool> InitContextAndIsTypeChecked;

      StringRef StringRepresentation;
      CaptureInfo Captures;
   };

   /// Retrieve the cached initializer context for the parameter's default
   /// argument without triggering a request.
   Optional<Initializer *> getCachedDefaultArgumentInitContext() const;

   enum class Flags : uint8_t {
      /// Whether or not this parameter is vargs.
         IsVariadic = 1 << 0,

      /// Whether or not this parameter is `@autoclosure`.
         IsAutoClosure = 1 << 1,
   };

   /// The default value, if any, along with flags.
   llvm::PointerIntPair<StoredDefaultArgument *, 2, OptionSet<Flags>>
      DefaultValueAndFlags;

   friend class ParamSpecifierRequest;

public:
   ParamDecl(SourceLoc specifierLoc, SourceLoc argumentNameLoc,
             Identifier argumentName, SourceLoc parameterNameLoc,
             Identifier parameterName, DeclContext *dc);

   /// Create a new ParamDecl identical to the first except without the interface type.
   static ParamDecl *cloneWithoutType(const AstContext &Ctx, ParamDecl *PD);

   /// Retrieve the argument (API) name for this function parameter.
   Identifier getArgumentName() const {
      return ArgumentNameAndDestructured.getPointer();
   }

   /// Retrieve the parameter (local) name for this function parameter.
   Identifier getParameterName() const { return getName(); }

   /// Retrieve the source location of the argument (API) name.
   ///
   /// The resulting source location will be valid if the argument name
   /// was specified separately from the parameter name.
   SourceLoc getArgumentNameLoc() const { return ArgumentNameLoc; }

   SourceLoc getParameterNameLoc() const { return ParameterNameLoc; }

   SourceLoc getSpecifierLoc() const { return SpecifierLoc; }

   /// Retrieve the TypeRepr corresponding to the parsed type of the parameter, if it exists.
   TypeRepr *getTypeRepr() const { return TyRepr; }
   void setTypeRepr(TypeRepr *repr) { TyRepr = repr; }

   bool isDestructured() const { return ArgumentNameAndDestructured.getInt(); }
   void setDestructured(bool repr) { ArgumentNameAndDestructured.setInt(repr); }

   DefaultArgumentKind getDefaultArgumentKind() const {
      return static_cast<DefaultArgumentKind>(Bits.ParamDecl.defaultArgumentKind);
   }
   bool isDefaultArgument() const {
      return getDefaultArgumentKind() != DefaultArgumentKind::None;
   }
   void setDefaultArgumentKind(DefaultArgumentKind K) {
      Bits.ParamDecl.defaultArgumentKind = static_cast<unsigned>(K);
   }

   /// Whether this parameter has a default argument expression available.
   ///
   /// Note that this will return false for deserialized declarations, which only
   /// have a textual representation of their default expression.
   bool hasDefaultExpr() const;

   /// Whether this parameter has a caller-side default argument expression
   /// such as the magic literal \c #function.
   bool hasCallerSideDefaultExpr() const;

   /// Retrieve the fully type-checked default argument expression for this
   /// parameter, or \c nullptr if there is no default expression.
   ///
   /// Note that while this will produce a type-checked expression for
   /// caller-side default arguments such as \c #function, this is done purely to
   /// check whether the code is valid. Such default arguments get re-created
   /// at the call site in order to have the correct context information.
   Expr *getTypeCheckedDefaultExpr() const;

   /// Retrieve the potentially un-type-checked default argument expression for
   /// this parameter, which can be queried for information such as its source
   /// range and textual representation. Returns \c nullptr if there is no
   /// default expression.
   Expr *getStructuralDefaultExpr() const {
      if (auto stored = DefaultValueAndFlags.getPointer())
         return stored->DefaultArg.dyn_cast<Expr *>();
      return nullptr;
   }

   VarDecl *getStoredProperty() const {
      if (auto stored = DefaultValueAndFlags.getPointer())
         return stored->DefaultArg.dyn_cast<VarDecl *>();
      return nullptr;
   }

   /// Sets a new default argument expression for this parameter. This should
   /// only be called internally by ParamDecl and AST walkers.
   ///
   /// \param E The new default argument.
   /// \param isTypeChecked Whether this argument should be used as the
   /// parameter's fully type-checked default argument.
   void setDefaultExpr(Expr *E, bool isTypeChecked);

   void setStoredProperty(VarDecl *var);

   /// Retrieve the initializer context for the parameter's default argument.
   Initializer *getDefaultArgumentInitContext() const;

   void setDefaultArgumentInitContext(Initializer *initContext);

   CaptureInfo getDefaultArgumentCaptureInfo() const {
      assert(DefaultValueAndFlags.getPointer());
      return DefaultValueAndFlags.getPointer()->Captures;
   }

   void setDefaultArgumentCaptureInfo(CaptureInfo captures);

   /// Extracts the text of the default argument attached to the provided
   /// ParamDecl, removing all inactive #if clauses and providing only the
   /// text of active #if clauses.
   ///
   /// For example, the default argument:
   /// ```
   /// {
   ///   #if false
   ///   print("false")
   ///   #else
   ///   print("true")
   ///   #endif
   /// }
   /// ```
   /// will return
   /// ```
   /// {
   ///   print("true")
   /// }
   /// ```
   /// \sa getDefaultValue
   StringRef getDefaultValueStringRepresentation(
      SmallVectorImpl<char> &scratch) const;

   void setDefaultValueStringRepresentation(StringRef stringRepresentation);

   /// Whether or not this parameter is varargs.
   bool isVariadic() const {
      return DefaultValueAndFlags.getInt().contains(Flags::IsVariadic);
   }
   void setVariadic(bool value = true) {
      auto flags = DefaultValueAndFlags.getInt();
      DefaultValueAndFlags.setInt(value ? flags | Flags::IsVariadic
                                        : flags - Flags::IsVariadic);
   }

   /// Whether or not this parameter is marked with `@autoclosure`.
   bool isAutoClosure() const {
      return DefaultValueAndFlags.getInt().contains(Flags::IsAutoClosure);
   }
   void setAutoClosure(bool value = true) {
      auto flags = DefaultValueAndFlags.getInt();
      DefaultValueAndFlags.setInt(value ? flags | Flags::IsAutoClosure
                                        : flags - Flags::IsAutoClosure);
   }

   /// Does this parameter reject temporary pointer conversions?
   bool isNonEphemeral() const {
      if (getAttrs().hasAttribute<NonEphemeralAttr>())
         return true;

      // Only pointer parameters can be non-ephemeral.
      auto ty = getInterfaceType();
      if (!ty->lookThroughSingleOptionalType()->getAnyPointerElementType())
         return false;

      // Enum element pointer parameters are always non-ephemeral.
      auto *parentDecl = getDeclContext()->getAsDecl();
      if (parentDecl && isa<EnumElementDecl>(parentDecl))
         return true;

      return false;
   }

   /// Attempt to apply an implicit `@_nonEphemeral` attribute to this parameter.
   void setNonEphemeralIfPossible() {
      // Don't apply the attribute if this isn't a pointer param.
      auto type = getInterfaceType();
      if (!type->lookThroughSingleOptionalType()->getAnyPointerElementType())
         return;

      if (!getAttrs().hasAttribute<NonEphemeralAttr>()) {
         auto &ctx = getAstContext();
         getAttrs().add(new (ctx) NonEphemeralAttr(/*IsImplicit*/ true));
      }
   }

   /// Remove the type of this varargs element designator, without the array
   /// type wrapping it.  A parameter like "Int..." will have formal parameter
   /// type of "[Int]" and this returns "Int".
   static Type getVarargBaseTy(Type VarArgT);

   /// Remove the type of this varargs element designator, without the array
   /// type wrapping it.
   Type getVarargBaseTy() const {
      assert(isVariadic());
      return getVarargBaseTy(getInterfaceType());
   }

   /// Determine whether this declaration is an anonymous closure parameter.
   bool isAnonClosureParam() const;

   using Specifier = ParamSpecifier;

   Optional<Specifier> getCachedSpecifier() const {
      if (Bits.ParamDecl.SpecifierComputed)
         return Specifier(Bits.ParamDecl.Specifier);

      return None;
   }

   /// Return the raw specifier value for this parameter.
   Specifier getSpecifier() const;
   void setSpecifier(Specifier Spec);

   /// Is the type of this parameter 'inout'?
   bool isInOut() const { return getSpecifier() == Specifier::InOut; }
   /// Is this an immutable 'shared' property?
   bool isShared() const { return getSpecifier() == Specifier::Shared; }
   /// Is this an immutable 'owned' property?
   bool isOwned() const { return getSpecifier() == Specifier::Owned; }

   bool isImmutable() const {
      return isImmutableSpecifier(getSpecifier());
   }
   static bool isImmutableSpecifier(Specifier sp) {
      switch (sp) {
         case Specifier::Default:
         case Specifier::Shared:
         case Specifier::Owned:
            return true;
         case Specifier::InOut:
            return false;
      }
      llvm_unreachable("unhandled specifier");
   }

   ValueOwnership getValueOwnership() const {
      return getValueOwnershipForSpecifier(getSpecifier());
   }

   static ValueOwnership getValueOwnershipForSpecifier(Specifier specifier) {
      switch (specifier) {
         case Specifier::Default:
            return ValueOwnership::Default;
         case Specifier::InOut:
            return ValueOwnership::InOut;
         case Specifier::Shared:
            return ValueOwnership::Shared;
         case Specifier::Owned:
            return ValueOwnership::Owned;
      }
      llvm_unreachable("unhandled specifier");
   }

   static Specifier
   getParameterSpecifierForValueOwnership(ValueOwnership ownership) {
      switch (ownership) {
         case ValueOwnership::Default:
            return Specifier::Default;
         case ValueOwnership::Shared:
            return Specifier::Shared;
         case ValueOwnership::InOut:
            return Specifier::InOut;
         case ValueOwnership::Owned:
            return Specifier::Owned;
      }
      llvm_unreachable("unhandled ownership");
   }

   SourceRange getSourceRange() const;

   AnyFunctionType::Param toFunctionParam(Type type = Type()) const;

   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Param;
   }
};

/// Describes the kind of subscripting used in Objective-C.
enum class ObjCSubscriptKind {
   /// Objective-C indexed subscripting, which is based on an integral
   /// index.
      Indexed,
   /// Objective-C keyed subscripting, which is based on an object
   /// argument or metatype thereof.
      Keyed
};

/// Declares a subscripting operator for a type.
///
/// A subscript declaration is defined as a get/set pair that produces a
/// specific type. For example:
///
/// \code
/// subscript (i : Int) -> String {
///   get { /* return ith String */ }
///   set { /* set ith string to value */ }
/// }
/// \endcode
///
/// A type with a subscript declaration can be used as the base of a subscript
/// expression a[i], where a is of the subscriptable type and i is the type
/// of the index. A subscript can have multiple indices:
///
/// \code
/// struct Matrix {
///   subscript (i : Int, j : Int) -> Double {
///     get { /* return element at position (i, j) */ }
///     set { /* set element at position (i, j) */ }
///   }
/// }
/// \endcode
///
/// A given type can have multiple subscript declarations, so long as the
/// signatures (indices and element type) are distinct.
///
class SubscriptDecl : public GenericContext, public AbstractStorageDecl {
   SourceLoc StaticLoc;
   SourceLoc ArrowLoc;
   SourceLoc EndLoc;
   ParameterList *Indices;
   TypeLoc ElementTy;

public:
   SubscriptDecl(DeclName Name,
                 SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
                 SourceLoc SubscriptLoc, ParameterList *Indices,
                 SourceLoc ArrowLoc, TypeLoc ElementTy, DeclContext *Parent,
                 GenericParamList *GenericParams)
      : GenericContext(DeclContextKind::SubscriptDecl, Parent, GenericParams),
        AbstractStorageDecl(DeclKind::Subscript,
                            StaticSpelling != StaticSpellingKind::None,
                            Parent, Name, SubscriptLoc,
           /*will be overwritten*/ StorageIsNotMutable),
        StaticLoc(StaticLoc), ArrowLoc(ArrowLoc),
        Indices(nullptr), ElementTy(ElementTy) {
      Bits.SubscriptDecl.StaticSpelling = static_cast<unsigned>(StaticSpelling);
      setIndices(Indices);
   }

   /// \returns the way 'static'/'class' was spelled in the source.
   StaticSpellingKind getStaticSpelling() const {
      return static_cast<StaticSpellingKind>(Bits.SubscriptDecl.StaticSpelling);
   }

   SourceLoc getStaticLoc() const { return StaticLoc; }
   SourceLoc getSubscriptLoc() const { return getNameLoc(); }

   SourceLoc getStartLoc() const {
      return getStaticLoc().isValid() ? getStaticLoc() : getSubscriptLoc();
   }
   SourceLoc getEndLoc() const { return EndLoc; }

   void setEndLoc(SourceLoc sl) { EndLoc = sl; }
   SourceRange getSourceRange() const;
   SourceRange getSignatureSourceRange() const;

   /// Retrieve the indices for this subscript operation.
   ParameterList *getIndices() { return Indices; }
   const ParameterList *getIndices() const { return Indices; }
   void setIndices(ParameterList *p);

   /// Retrieve the type of the element referenced by a subscript
   /// operation.
   Type getElementInterfaceType() const;
   TypeLoc &getElementTypeLoc() { return ElementTy; }
   const TypeLoc &getElementTypeLoc() const { return ElementTy; }

   /// Determine the kind of Objective-C subscripting this declaration
   /// implies.
   ObjCSubscriptKind getObjCSubscriptKind() const;

   SubscriptDecl *getOverriddenDecl() const {
      return cast_or_null<SubscriptDecl>(
         AbstractStorageDecl::getOverriddenDecl());
   }

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Subscript;
   }

   static bool classof(const DeclContext *DC) {
      if (auto D = DC->getAsDecl())
         return classof(D);
      return false;
   }

   using DeclContext::operator new;
   using Decl::getAstContext;
};

/// Encodes imported-as-member status for C functions that get imported
/// as methods.
class ImportAsMemberStatus {
   friend class AbstractFunctionDecl;

   // non-0 denotes import-as-member. 1 denotes no self index. n+2 denotes self
   // index of n
   uint8_t rawValue;

public:
   ImportAsMemberStatus(uint8_t rawValue = 0) : rawValue(rawValue) {}

   uint8_t getRawValue() const { return rawValue; }

   bool isImportAsMember() const { return rawValue != 0; }
   bool isInstance() const { return rawValue >= 2; }
   bool isStatic() const { return rawValue == 1; }
   uint8_t getSelfIndex() const {
      assert(isInstance() && "not set");
      return rawValue - 2;
   }
   void setStatic() {
      assert(!isStatic() && "already set");
      rawValue = 1;
   }
   void setSelfIndex(uint8_t idx) {
      assert(!isImportAsMember() && "already set");
      assert(idx <= UINT8_MAX-2 && "out of bounds");
      rawValue = idx + 2;
   }
};

/// Base class for function-like declarations.
class AbstractFunctionDecl : public GenericContext, public ValueDecl {
   friend class NeedsNewVTableEntryRequest;

public:
   enum class BodyKind {
      /// The function did not have a body in the source code file.
         None,

      /// Function body is delayed, to be parsed later.
         Unparsed,

      /// Function body is parsed and available as an AST subtree.
         Parsed,

      /// Function body is not available, although it was written in the source.
         Skipped,

      /// Function body will be synthesized on demand.
         Synthesize,

      /// Function body is present and type-checked.
         TypeChecked,

      /// This is a memberwise initializer that will be synthesized by SILGen.
         MemberwiseInitializer,

      /// Function body text was deserialized from a .swiftmodule.
         Deserialized

      // This enum currently needs to fit in a 3-bit bitfield.
   };

   BodyKind getBodyKind() const {
      return BodyKind(Bits.AbstractFunctionDecl.BodyKind);
   }

   struct BodySynthesizer {
      std::pair<BraceStmt *, bool> (* Fn)(AbstractFunctionDecl *, void *);
      void *Context;
   };

private:
   ParameterList *Params;

protected:
   // If a function has a body at all, we have either a parsed body AST node or
   // we have saved the end location of the unparsed body.
   union {
      /// This enum member is active if getBodyKind() is BodyKind::Parsed or
      /// BodyKind::TypeChecked.
      BraceStmt *Body;

      /// This enum member is active if getBodyKind() is BodyKind::Deserialized.
      StringRef BodyStringRepresentation;

      /// This enum member is active if getBodyKind() == BodyKind::Synthesize.
      BodySynthesizer Synthesizer;

      /// The location of the function body when the body is delayed or skipped.
      ///
      /// This enum member is active if getBodyKind() is BodyKind::Unparsed or
      /// BodyKind::Skipped.
      SourceRange BodyRange;
   };

   friend class ParseAbstractFunctionBodyRequest;

   CaptureInfo Captures;

   /// Location of the 'throws' token.
   SourceLoc ThrowsLoc;

   struct {
      unsigned NeedsNewVTableEntryComputed : 1;
      unsigned NeedsNewVTableEntry : 1;
   } LazySemanticInfo = { };

   AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent, DeclName Name,
                        SourceLoc NameLoc, bool Throws, SourceLoc ThrowsLoc,
                        bool HasImplicitSelfDecl,
                        GenericParamList *GenericParams)
      : GenericContext(DeclContextKind::AbstractFunctionDecl, Parent, GenericParams),
        ValueDecl(Kind, Parent, Name, NameLoc),
        Body(nullptr), ThrowsLoc(ThrowsLoc) {
      setBodyKind(BodyKind::None);
      Bits.AbstractFunctionDecl.HasImplicitSelfDecl = HasImplicitSelfDecl;
      Bits.AbstractFunctionDecl.Overridden = false;
      Bits.AbstractFunctionDecl.Throws = Throws;
      Bits.AbstractFunctionDecl.Synthesized = false;
      Bits.AbstractFunctionDecl.HasSingleExpressionBody = false;
   }

   void setBodyKind(BodyKind K) {
      Bits.AbstractFunctionDecl.BodyKind = unsigned(K);
   }

public:
   void setHasSingleExpressionBody(bool Has = true) {
      Bits.AbstractFunctionDecl.HasSingleExpressionBody = Has;
   }

   bool hasSingleExpressionBody() const {
      return Bits.AbstractFunctionDecl.HasSingleExpressionBody;
   }

   Expr *getSingleExpressionBody() const;
   void setSingleExpressionBody(Expr *NewBody);

   /// Returns the string for the base name, or "_" if this is unnamed.
   StringRef getNameStr() const {
      assert(!getFullName().isSpecial() && "Cannot get string for special names");
      return hasName() ? getBaseName().getIdentifier().str() : "_";
   }

   /// Should this declaration be treated as if annotated with transparent
   /// attribute.
   bool isTransparent() const;

   // Expose our import as member status
   ImportAsMemberStatus getImportAsMemberStatus() const {
      return ImportAsMemberStatus(Bits.AbstractFunctionDecl.IAMStatus);
   }
   bool isImportAsMember() const {
      return getImportAsMemberStatus().isImportAsMember();
   }
   bool isImportAsInstanceMember() const {
      return getImportAsMemberStatus().isInstance();
   }
   bool isImportAsStaticMember() const {
      return getImportAsMemberStatus().isStatic();
   }
   uint8_t getSelfIndex() const {
      return getImportAsMemberStatus().getSelfIndex();
   }

   void setImportAsStaticMember() {
      auto newValue = getImportAsMemberStatus();
      newValue.setStatic();
      Bits.AbstractFunctionDecl.IAMStatus = newValue.getRawValue();
   }
   void setSelfIndex(uint8_t idx) {
      auto newValue = getImportAsMemberStatus();
      newValue.setSelfIndex(idx);
      Bits.AbstractFunctionDecl.IAMStatus = newValue.getRawValue();
   }

   /// Retrieve the location of the 'throws' keyword, if present.
   SourceLoc getThrowsLoc() const { return ThrowsLoc; }

   /// Returns true if the function body throws.
   bool hasThrows() const { return Bits.AbstractFunctionDecl.Throws; }

   // FIXME: Hack that provides names with keyword arguments for accessors.
   DeclName getEffectiveFullName() const;

   /// Returns true if the function has a body written in the source file.
   ///
   /// Note that a true return value does not imply that the body was actually
   /// parsed.
   bool hasBody() const {
      return getBodyKind() != BodyKind::None &&
             getBodyKind() != BodyKind::Skipped;
   }

   /// Returns true if the text of this function's body can be retrieved either
   /// by extracting the text from the source buffer or reading the inlinable
   /// body from a deserialized swiftmodule.
   bool hasInlinableBodyText() const;

   /// Returns the function body, if it was parsed, or nullptr otherwise.
   ///
   /// Note that a null return value does not imply that the source code did not
   /// have a body for this function.
   ///
   /// \sa hasBody()
   BraceStmt *getBody(bool canSynthesize = true) const;

   void setBody(BraceStmt *S, BodyKind NewBodyKind = BodyKind::Parsed) {
      assert(getBodyKind() != BodyKind::Skipped &&
             "cannot set a body if it was skipped");

      Body = S;
      setBodyKind(NewBodyKind);
   }

   /// Note that the body was skipped for this function.  Function body
   /// cannot be attached after this call.
   void setBodySkipped(SourceRange bodyRange) {
      // FIXME: Remove 'Parsed' from this once we can delay parsing function
      //        bodies. Right now -experimental-skip-non-inlinable-function-bodies
      //        requires being able to change the state from Parsed to Skipped,
      //        because we're still eagerly parsing function bodies.
      assert(getBodyKind() == BodyKind::None ||
             getBodyKind() == BodyKind::Unparsed ||
             getBodyKind() == BodyKind::Parsed);
      assert(bodyRange.isValid());
      BodyRange = bodyRange;
      setBodyKind(BodyKind::Skipped);
   }

   /// Note that parsing for the body was delayed.
   void setBodyDelayed(SourceRange bodyRange) {
      assert(getBodyKind() == BodyKind::None);
      assert(bodyRange.isValid());
      BodyRange = bodyRange;
      setBodyKind(BodyKind::Unparsed);
   }

   /// Provide the parsed body for the function.
   void setBodyParsed(BraceStmt *S) {
      setBody(S, BodyKind::Parsed);
   }

   /// Note that parsing for the body was delayed.
   ///
   /// The function should return the body statement and a flag indicating
   /// whether that body is already type-checked.
   void setBodySynthesizer(
      std::pair<BraceStmt *, bool> (* fn)(AbstractFunctionDecl *, void *),
      void *context = nullptr) {
      assert(getBodyKind() == BodyKind::None);
      Synthesizer = {fn, context};
      setBodyKind(BodyKind::Synthesize);
   }

   /// Note that this is a memberwise initializer and thus the body will be
   /// generated by SILGen.
   void setIsMemberwiseInitializer() {
      assert(getBodyKind() == BodyKind::None);
      assert(isa<ConstructorDecl>(this));
      setBodyKind(BodyKind::MemberwiseInitializer);
   }

   /// Gets the body of this function, stripping the unused portions of #if
   /// configs inside the body. If this function was not deserialized from a
   /// .swiftmodule, this body is reconstructed from the original
   /// source buffer.
   StringRef getInlinableBodyText(SmallVectorImpl<char> &scratch) const;

   void setBodyStringRepresentation(StringRef body) {
      assert(getBodyKind() == BodyKind::None);
      setBodyKind(BodyKind::Deserialized);
      BodyStringRepresentation = body;
   }

   bool isBodyTypeChecked() const {
      return getBodyKind() == BodyKind::TypeChecked;
   }

   bool isBodySkipped() const {
      return getBodyKind() == BodyKind::Skipped;
   }

   bool isMemberwiseInitializer() const {
      return getBodyKind() == BodyKind::MemberwiseInitializer;
   }

   /// For a method of a class, checks whether it will require a new entry in the
   /// vtable.
   bool needsNewVTableEntry() const;

   bool isEffectiveLinkageMoreVisibleThan(ValueDecl *other) const {
      return (std::min(getEffectiveAccess(), AccessLevel::Public) >
              std::min(other->getEffectiveAccess(), AccessLevel::Public));
   }

   bool isSynthesized() const {
      return Bits.AbstractFunctionDecl.Synthesized;
   }

   void setSynthesized(bool value = true) {
      Bits.AbstractFunctionDecl.Synthesized = value;
   }

public:
   /// Retrieve the source range of the function body.
   SourceRange getBodySourceRange() const;

   /// Retrieve the source range of the function declaration name + patterns.
   SourceRange getSignatureSourceRange() const;

   CaptureInfo getCaptureInfo() const { return Captures; }
   void setCaptureInfo(CaptureInfo captures) { Captures = captures; }

   /// Retrieve the Objective-C selector that names this method.
//   ObjCSelector getObjCSelector(DeclName preferredName = DeclName(),
//                                bool skipIsObjCResolution = false) const;

   /// Determine whether the given method would produce an Objective-C
   /// instance method.
//   bool isObjCInstanceMethod() const;

   /// Determine whether the name of an argument is an API name by default
   /// depending on the function context.
   bool argumentNameIsAPIByDefault() const;

   /// Retrieve the function's parameter list, not including 'self' if present.
   ParameterList *getParameters() {
      return Params;
   }
   const ParameterList *getParameters() const {
      return Params;
   }

   void setParameters(ParameterList *Params);

   bool hasImplicitSelfDecl() const {
      return Bits.AbstractFunctionDecl.HasImplicitSelfDecl;
   }

   ParamDecl **getImplicitSelfDeclStorage();

   /// Retrieve the implicit 'self' parameter for methods. Returns nullptr for
   /// free functions.
   const ParamDecl *getImplicitSelfDecl(bool createIfNeeded=true) const {
      return const_cast<AbstractFunctionDecl*>(this)
         ->getImplicitSelfDecl(createIfNeeded);
   }
   ParamDecl *getImplicitSelfDecl(bool createIfNeeded=true);

   /// Retrieve the declaration that this method overrides, if any.
   AbstractFunctionDecl *getOverriddenDecl() const {
      return cast_or_null<AbstractFunctionDecl>(ValueDecl::getOverriddenDecl());
   }

   /// Whether the declaration is later overridden in the module
   ///
   /// Overrides are resolved during type checking; only query this field after
   /// the whole module has been checked
   bool isOverridden() const { return Bits.AbstractFunctionDecl.Overridden; }

   /// The declaration has been overridden in the module
   ///
   /// Resolved during type checking
   void setIsOverridden() { Bits.AbstractFunctionDecl.Overridden = true; }

   /// Set information about the foreign error convention used by this
   /// declaration.
   void setForeignErrorConvention(const ForeignErrorConvention &convention);

   /// Get information about the foreign error convention used by this
   /// declaration, given that it is @objc and 'throws'.
   Optional<ForeignErrorConvention> getForeignErrorConvention() const;

   /// If this is a foreign C function imported as a method, get the index of
   /// the foreign parameter imported as `self`. If the function is imported
   /// as a static method, `-1` is returned to represent the `self` parameter
   /// being dropped altogether. `None` is returned for a normal function
   /// or method.
   Optional<int> getForeignFunctionAsMethodSelfParameterIndex() const;

   static bool classof(const Decl *D) {
      return D->getKind() >= DeclKind::First_AbstractFunctionDecl &&
             D->getKind() <= DeclKind::Last_AbstractFunctionDecl;
   }

   static bool classof(const DeclContext *DC) {
      if (auto D = DC->getAsDecl())
         return classof(D);
      return false;
   }

   /// True if the declaration is forced to be statically dispatched.
   bool hasForcedStaticDispatch() const;

   /// Get the type of this declaration without the Self clause.
   /// Asserts if not in type context.
   Type getMethodInterfaceType() const;

   /// Tests if this is a function returning a DynamicSelfType, or a
   /// constructor.
   bool hasDynamicSelfResult() const;

   using DeclContext::operator new;
   using Decl::getAstContext;
};

class OperatorDecl;

enum class SelfAccessKind : uint8_t {
   NonMutating,
   Mutating,
   Consuming,
};

/// Diagnostic printing of \c SelfAccessKind.
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SelfAccessKind SAK);

/// FuncDecl - 'func' declaration.
class FuncDecl : public AbstractFunctionDecl {
   friend class AbstractFunctionDecl;
   friend class SelfAccessKindRequest;
   friend class IsStaticRequest;

   SourceLoc StaticLoc;  // Location of the 'static' token or invalid.
   SourceLoc FuncLoc;    // Location of the 'func' token.

   TypeLoc FnRetType;

protected:
   FuncDecl(DeclKind Kind,
            SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
            SourceLoc FuncLoc,
            DeclName Name, SourceLoc NameLoc,
            bool Throws, SourceLoc ThrowsLoc,
            bool HasImplicitSelfDecl,
            GenericParamList *GenericParams, DeclContext *Parent)
      : AbstractFunctionDecl(Kind, Parent,
                             Name, NameLoc,
                             Throws, ThrowsLoc,
                             HasImplicitSelfDecl, GenericParams),
        StaticLoc(StaticLoc), FuncLoc(FuncLoc) {
      assert(!Name.getBaseName().isSpecial());

      Bits.FuncDecl.StaticSpelling = static_cast<unsigned>(StaticSpelling);

      Bits.FuncDecl.ForcedStaticDispatch = false;
      Bits.FuncDecl.SelfAccess =
         static_cast<unsigned>(SelfAccessKind::NonMutating);
      Bits.FuncDecl.SelfAccessComputed = false;
      Bits.FuncDecl.IsStaticComputed = false;
      Bits.FuncDecl.IsStatic = false;
   }

private:
   static FuncDecl *createImpl(AstContext &Context, SourceLoc StaticLoc,
                               StaticSpellingKind StaticSpelling,
                               SourceLoc FuncLoc,
                               DeclName Name, SourceLoc NameLoc,
                               bool Throws, SourceLoc ThrowsLoc,
                               GenericParamList *GenericParams,
                               DeclContext *Parent,
                               ClangNode ClangN);

   Optional<SelfAccessKind> getCachedSelfAccessKind() const {
      if (Bits.FuncDecl.SelfAccessComputed)
         return static_cast<SelfAccessKind>(Bits.FuncDecl.SelfAccess);

      return None;
   }

   Optional<bool> getCachedIsStatic() const {
      if (Bits.FuncDecl.IsStaticComputed)
         return Bits.FuncDecl.IsStatic;

      return None;
   }

public:
   /// Factory function only for use by deserialization.
   static FuncDecl *createDeserialized(AstContext &Context, SourceLoc StaticLoc,
                                       StaticSpellingKind StaticSpelling,
                                       SourceLoc FuncLoc,
                                       DeclName Name, SourceLoc NameLoc,
                                       bool Throws, SourceLoc ThrowsLoc,
                                       GenericParamList *GenericParams,
                                       DeclContext *Parent);

   static FuncDecl *create(AstContext &Context, SourceLoc StaticLoc,
                           StaticSpellingKind StaticSpelling,
                           SourceLoc FuncLoc,
                           DeclName Name, SourceLoc NameLoc,
                           bool Throws, SourceLoc ThrowsLoc,
                           GenericParamList *GenericParams,
                           ParameterList *ParameterList,
                           TypeLoc FnRetType, DeclContext *Parent,
                           ClangNode ClangN = ClangNode());

   Identifier getName() const { return getFullName().getBaseIdentifier(); }

   bool isStatic() const;

   /// \returns the way 'static'/'class' was spelled in the source.
   StaticSpellingKind getStaticSpelling() const {
      return static_cast<StaticSpellingKind>(Bits.FuncDecl.StaticSpelling);
   }
   /// \returns the way 'static'/'class' should be spelled for this declaration.
   StaticSpellingKind getCorrectStaticSpelling() const;
   void setStatic(bool IsStatic = true) {
      Bits.FuncDecl.IsStaticComputed = true;
      Bits.FuncDecl.IsStatic = IsStatic;
   }

   bool isMutating() const {
      return getSelfAccessKind() == SelfAccessKind::Mutating;
   }
   bool isNonMutating() const {
      return getSelfAccessKind() == SelfAccessKind::NonMutating;
   }
   bool isConsuming() const {
      return getSelfAccessKind() == SelfAccessKind::Consuming;
   }
   bool isCallAsFunctionMethod() const;

   SelfAccessKind getSelfAccessKind() const;

   void setSelfAccessKind(SelfAccessKind mod) {
      Bits.FuncDecl.SelfAccess = static_cast<unsigned>(mod);
      Bits.FuncDecl.SelfAccessComputed = true;
   }

   SourceLoc getStaticLoc() const { return StaticLoc; }
   SourceLoc getFuncLoc() const { return FuncLoc; }

   SourceLoc getStartLoc() const {
      return StaticLoc.isValid() && !isa<AccessorDecl>(this)
             ? StaticLoc : FuncLoc;
   }
   SourceRange getSourceRange() const;

   TypeLoc &getBodyResultTypeLoc() { return FnRetType; }
   const TypeLoc &getBodyResultTypeLoc() const { return FnRetType; }

   /// Retrieve the result interface type of this function.
   Type getResultInterfaceType() const;

   /// isUnaryOperator - Determine whether this is a unary operator
   /// implementation.  This check is a syntactic rather than type-based check,
   /// which looks at the number of parameters specified, in order to allow
   /// for the definition of unary operators on tuples, as in:
   ///
   ///   prefix func + (param : (a:Int, b:Int))
   ///
   /// This also allows the unary-operator-ness of a func decl to be determined
   /// prior to type checking.
   bool isUnaryOperator() const;

   /// isBinaryOperator - Determine whether this is a binary operator
   /// implementation.  This check is a syntactic rather than type-based check,
   /// which looks at the number of parameters specified, in order to allow
   /// distinguishing a binary operator from a unary operator on tuples, as in:
   ///
   ///   prefix func + (_:(a:Int, b:Int)) // unary operator +(1,2)
   ///   infix func  + (a:Int, b:Int)     // binary operator 1 + 2
   ///
   /// This also allows the binary-operator-ness of a func decl to be determined
   /// prior to type checking.
   bool isBinaryOperator() const;

   void getLocalCaptures(SmallVectorImpl<CapturedValue> &Result) const {
      return getCaptureInfo().getLocalCaptures(Result);
   }

   ParamDecl **getImplicitSelfDeclStorage();

   /// Get the supertype method this method overrides, if any.
   FuncDecl *getOverriddenDecl() const {
      return cast_or_null<FuncDecl>(AbstractFunctionDecl::getOverriddenDecl());
   }

   OperatorDecl *getOperatorDecl() const;

   /// Returns true if the function is forced to be statically dispatched.
   bool hasForcedStaticDispatch() const {
      return Bits.FuncDecl.ForcedStaticDispatch;
   }
   void setForcedStaticDispatch(bool flag) {
      Bits.FuncDecl.ForcedStaticDispatch = flag;
   }

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Func ||
             D->getKind() == DeclKind::Accessor;
   }
   static bool classof(const AbstractFunctionDecl *D) {
      return classof(static_cast<const Decl*>(D));
   }
   static bool classof(const DeclContext *DC) {
      if (auto D = DC->getAsDecl())
         return classof(D);
      return false;
   }

   /// True if the function is a defer body.
   bool isDeferBody() const;

   /// Perform basic checking to determine whether the @IBAction or
   /// @IBSegueAction attribute can be applied to this function.
   bool isPotentialIBActionTarget() const;
};

/// This represents an accessor function, such as a getter or setter.
class AccessorDecl final : public FuncDecl {
   /// Location of the accessor keyword, e.g. 'set'.
   SourceLoc AccessorKeywordLoc;

   AbstractStorageDecl *Storage;

   AccessorDecl(SourceLoc declLoc, SourceLoc accessorKeywordLoc,
                AccessorKind accessorKind, AbstractStorageDecl *storage,
                SourceLoc staticLoc, StaticSpellingKind staticSpelling,
                bool throws, SourceLoc throwsLoc,
                bool hasImplicitSelfDecl, GenericParamList *genericParams,
                DeclContext *parent)
      : FuncDecl(DeclKind::Accessor,
                 staticLoc, staticSpelling, /*func loc*/ declLoc,
      /*name*/ Identifier(), /*name loc*/ declLoc,
                 throws, throwsLoc, hasImplicitSelfDecl, genericParams, parent),
        AccessorKeywordLoc(accessorKeywordLoc),
        Storage(storage) {
      Bits.AccessorDecl.AccessorKind = unsigned(accessorKind);
   }

   static AccessorDecl *createImpl(AstContext &ctx,
                                   SourceLoc declLoc,
                                   SourceLoc accessorKeywordLoc,
                                   AccessorKind accessorKind,
                                   AbstractStorageDecl *storage,
                                   SourceLoc staticLoc,
                                   StaticSpellingKind staticSpelling,
                                   bool throws, SourceLoc throwsLoc,
                                   GenericParamList *genericParams,
                                   DeclContext *parent,
                                   ClangNode clangNode);

   Optional<bool> getCachedIsTransparent() const {
      if (Bits.AccessorDecl.IsTransparentComputed)
         return Bits.AccessorDecl.IsTransparent;
      return None;
   }

   friend class IsAccessorTransparentRequest;

public:
   static AccessorDecl *createDeserialized(AstContext &ctx,
                                           SourceLoc declLoc,
                                           SourceLoc accessorKeywordLoc,
                                           AccessorKind accessorKind,
                                           AbstractStorageDecl *storage,
                                           SourceLoc staticLoc,
                                           StaticSpellingKind staticSpelling,
                                           bool throws, SourceLoc throwsLoc,
                                           GenericParamList *genericParams,
                                           DeclContext *parent);

   static AccessorDecl *create(AstContext &ctx, SourceLoc declLoc,
                               SourceLoc accessorKeywordLoc,
                               AccessorKind accessorKind,
                               AbstractStorageDecl *storage,
                               SourceLoc staticLoc,
                               StaticSpellingKind staticSpelling,
                               bool throws, SourceLoc throwsLoc,
                               GenericParamList *genericParams,
                               ParameterList *parameterList,
                               TypeLoc fnRetType, DeclContext *parent,
                               ClangNode clangNode = ClangNode());

   SourceLoc getAccessorKeywordLoc() const { return AccessorKeywordLoc; }

   AbstractStorageDecl *getStorage() const {
      return Storage;
   }

   AccessorKind getAccessorKind() const {
      return AccessorKind(Bits.AccessorDecl.AccessorKind);
   }

   bool isGetter() const { return getAccessorKind() == AccessorKind::Get; }
   bool isSetter() const { return getAccessorKind() == AccessorKind::Set; }
   bool isAnyAddressor() const {
      auto kind = getAccessorKind();
      return kind == AccessorKind::Address
             || kind == AccessorKind::MutableAddress;
   }

   /// isGetterOrSetter - Determine whether this is specifically a getter or
   /// a setter, as opposed to some other kind of accessor.
   ///
   /// For example, only getters and setters can be exposed to Objective-C.
   bool isGetterOrSetter() const { return isGetter() || isSetter(); }

   bool isObservingAccessor() const {
      switch (getAccessorKind()) {
#define OBSERVING_ACCESSOR(ID, KEYWORD) \
    case AccessorKind::ID: return true;
#define ACCESSOR(ID) \
    case AccessorKind::ID: return false;
#include "polarphp/ast/AccessorKindsDef.h"
      }
      llvm_unreachable("bad accessor kind");
   }

   /// \returns true if this is non-mutating due to applying a 'mutating'
   /// attribute. For example a "mutating set" accessor.
   bool isExplicitNonMutating() const;

   /// Is the accesor one of the kinds that's assumed nonmutating by default?
   bool isAssumedNonMutating() const;

   /// Is this accessor one of the kinds that's implicitly a coroutine?
   bool isCoroutine() const {
      switch (getAccessorKind()) {
#define COROUTINE_ACCESSOR(ID, KEYWORD) \
    case AccessorKind::ID: return true;
#define ACCESSOR(ID) \
    case AccessorKind::ID: return false;
#include "polarphp/ast/AccessorKindsDef.h"
      }
      llvm_unreachable("bad accessor kind");
   }

   void setIsTransparent(bool transparent) {
      Bits.AccessorDecl.IsTransparent = transparent;
      Bits.AccessorDecl.IsTransparentComputed = 1;
   }

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Accessor;
   }
   static bool classof(const AbstractFunctionDecl *D) {
      return classof(static_cast<const Decl*>(D));
   }
   static bool classof(const DeclContext *DC) {
      if (auto D = DC->getAsDecl())
         return classof(D);
      return false;
   }
};

inline AccessorDecl *
AbstractStorageDecl::AccessorRecord::getAccessor(AccessorKind kind) const {
   if (auto optIndex = AccessorIndices[unsigned(kind)]) {
      auto accessor = getAllAccessors()[optIndex - 1];
      assert(accessor && accessor->getAccessorKind() == kind);
      return accessor;
   }
   return nullptr;
}

/// This represents a 'case' declaration in an 'enum', which may declare
/// one or more individual comma-separated EnumElementDecls.
class EnumCaseDecl final : public Decl,
                           private llvm::TrailingObjects<EnumCaseDecl, EnumElementDecl *> {
   friend TrailingObjects;
   friend class Decl;
   SourceLoc CaseLoc;

   EnumCaseDecl(SourceLoc CaseLoc,
                ArrayRef<EnumElementDecl *> Elements,
                DeclContext *DC)
      : Decl(DeclKind::EnumCase, DC),
        CaseLoc(CaseLoc)
   {
      Bits.EnumCaseDecl.NumElements = Elements.size();
      std::uninitialized_copy(Elements.begin(), Elements.end(),
                              getTrailingObjects<EnumElementDecl *>());
   }
   SourceLoc getLocFromSource() const { return CaseLoc; }

public:
   static EnumCaseDecl *create(SourceLoc CaseLoc,
                               ArrayRef<EnumElementDecl*> Elements,
                               DeclContext *DC);

   /// Get the list of elements declared in this case.
   ArrayRef<EnumElementDecl *> getElements() const {
      return {getTrailingObjects<EnumElementDecl *>(),
              Bits.EnumCaseDecl.NumElements};
   }
   SourceRange getSourceRange() const;

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::EnumCase;
   }
};

/// This represents a single case of an 'enum' declaration.
///
/// For example, the X, Y, and Z in this enum:
///
/// \code
///   enum V {
///     case X(Int), Y(Int)
///     case Z
///   }
/// \endcode
///
/// The type of an EnumElementDecl is always the EnumType for the containing
/// enum. EnumElementDecls are represented in the AST as members of their
/// parent EnumDecl, although syntactically they are subordinate to the
/// EnumCaseDecl.
class EnumElementDecl : public DeclContext, public ValueDecl {
   friend class EnumRawValuesRequest;

   /// This is the type specified with the enum element, for
   /// example 'Int' in 'case Y(Int)'.  This is null if there is no type
   /// associated with this element, as in 'case Z' or in all elements of enum
   /// definitions.
   ParameterList *Params;

   SourceLoc EqualsLoc;

   /// The raw value literal for the enum element, or null.
   LiteralExpr *RawValueExpr;

public:
   EnumElementDecl(SourceLoc IdentifierLoc, DeclName Name,
                   ParameterList *Params,
                   SourceLoc EqualsLoc,
                   LiteralExpr *RawValueExpr,
                   DeclContext *DC);

   Identifier getName() const { return getFullName().getBaseIdentifier(); }

   /// Returns the string for the base name, or "_" if this is unnamed.
   StringRef getNameStr() const {
      assert(!getFullName().isSpecial() && "Cannot get string for special names");
      return hasName() ? getBaseName().getIdentifier().str() : "_";
   }

   Type getArgumentInterfaceType() const;

   void setParameterList(ParameterList *params);
   ParameterList *getParameterList() const { return Params; }

   /// Retrieves a fully typechecked raw value expression associated
   /// with this enum element, if it exists.
   LiteralExpr *getRawValueExpr() const;

   /// Retrieves a "structurally" checked raw value expression associated
   /// with this enum element, if it exists.
   ///
   /// The structural raw value may or may not have a type set, but it is
   /// guaranteed to be suitable for retrieving any non-semantic information
   /// like digit text for an integral raw value or user text for a string raw value.
   LiteralExpr *getStructuralRawValueExpr() const;

   /// Reset the raw value expression.
   void setRawValueExpr(LiteralExpr *e);

   /// Return the containing EnumDecl.
   EnumDecl *getParentEnum() const {
      return cast<EnumDecl>(getDeclContext());
   }

   /// Return the containing EnumCaseDecl.
   EnumCaseDecl *getParentCase() const;

   SourceLoc getStartLoc() const {
      return getNameLoc();
   }
   SourceRange getSourceRange() const;

   bool hasAssociatedValues() const {
      return getParameterList() != nullptr;
   }

   /// True if the case is marked 'indirect'.
   bool isIndirect() const {
      return getAttrs().hasAttribute<IndirectAttr>();
   }

   /// Do not call this!
   /// It exists to let the AST walkers get the raw value without forcing a request.
   LiteralExpr *getRawValueUnchecked() const { return RawValueExpr; }

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::EnumElement;
   }

   static bool classof(const DeclContext *DC) {
      if (auto D = DC->getAsDecl())
         return classof(D);
      return false;
   }

   using DeclContext::operator new;
   using Decl::getAstContext;
};

inline SourceRange EnumCaseDecl::getSourceRange() const {
   auto subRange = getElements().back()->getSourceRange();
   if (subRange.isValid())
      return {CaseLoc, subRange.end};
   return {};
}

/// Describes the kind of initializer.
enum class CtorInitializerKind {
   /// A designated initializer is an initializer responsible for initializing
   /// the stored properties of the current class and chaining to a superclass's
   /// designated initializer (for non-root classes).
   ///
   /// Designated initializers are never inherited.
      Designated,

   /// A convenience initializer is an initializer that initializes a complete
   /// object by delegating to another initializer (eventually reaching a
   /// designated initializer).
   ///
   /// Convenience initializers are inherited into subclasses that override
   /// all of their superclass's designated initializers.
      Convenience,

   /// A convenience factory initializer is a convenience initializer introduced
   /// by an imported Objective-C factory method.
   ///
   /// Convenience factory initializers cannot be expressed directly in
   /// Swift; rather, they are produced by the Clang importer when importing
   /// an instancetype factory method from Objective-C.
      ConvenienceFactory,

   /// A factory initializer is an initializer that is neither designated nor
   /// convenience: it can be used to create an object of the given type, but
   /// cannot be chained to via "super.init" nor is it inherited.
   ///
   /// A factory initializer is written with a return type of the class name
   /// itself. FIXME: However, this is only a presentation form, and at present
   /// the only factory initializers are produced by importing an Objective-C
   /// factory method that does not return instancetype.
   ///
   /// FIXME: Arguably, structs and enums only have factory initializers, and
   /// using designated initializers for them is a misnomer.
      Factory
};

/// ConstructorDecl - Declares a constructor for a type.  For example:
///
/// \code
/// struct X {
///   var x : Int
///   init(i : Int) {
///      x = i
///   }
/// }
/// \endcode
class ConstructorDecl : public AbstractFunctionDecl {
   /// The location of the '!' or '?' for a failable initializer.
   SourceLoc FailabilityLoc;

   ParamDecl *SelfDecl;

   /// The interface type of the initializing constructor.
   Type InitializerInterfaceType;

   /// The typechecked call to super.init expression, which needs to be
   /// inserted at the end of the initializer by SILGen.
   Expr *CallToSuperInit = nullptr;

public:
   ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
                   bool Failable, SourceLoc FailabilityLoc,
                   bool Throws, SourceLoc ThrowsLoc,
                   ParameterList *BodyParams,
                   GenericParamList *GenericParams,
                   DeclContext *Parent);

   SourceLoc getConstructorLoc() const { return getNameLoc(); }
   SourceLoc getStartLoc() const { return getConstructorLoc(); }
   SourceRange getSourceRange() const;

   /// Get the interface type of the constructed object.
   Type getResultInterfaceType() const;

   /// Get the interface type of the initializing constructor.
   Type getInitializerInterfaceType();

   /// Get the typechecked call to super.init expression, which needs to be
   /// inserted at the end of the initializer by SILGen.
   Expr *getSuperInitCall() { return CallToSuperInit; }
   void setSuperInitCall(Expr *CallExpr) { CallToSuperInit = CallExpr; }

   ParamDecl **getImplicitSelfDeclStorage() { return &SelfDecl; }

   /// Specifies the kind of initialization call performed within the body
   /// of the constructor, e.g., self.init or super.init.
   enum class BodyInitKind {
      /// There are no calls to self.init or super.init.
         None,
      /// There is a call to self.init, which delegates to another (peer)
      /// initializer.
         Delegating,
      /// There is a call to super.init, which chains to a superclass initializer.
         Chained,
      /// There are no calls to self.init or super.init explicitly in the body of
      /// the constructor, but a 'super.init' call will be implicitly added
      /// by semantic analysis.
         ImplicitChained
   };

   /// Determine whether the body of this constructor contains any delegating
   /// or superclass initializations (\c self.init or \c super.init,
   /// respectively) within its body.
   ///
   /// \param diags If non-null, this check will ensure that the constructor
   /// body is consistent in its use of delegation vs. chaining and emit any
   /// diagnostics through the given diagnostic engine.
   ///
   /// \param init If non-null and there is an explicit \c self.init or
   /// \c super.init within the body, will be set to point at that
   /// initializer.
   BodyInitKind getDelegatingOrChainedInitKind(DiagnosticEngine *diags,
                                               ApplyExpr **init = nullptr) const;

   /// Whether this constructor is required.
   bool isRequired() const {
      return getAttrs().hasAttribute<RequiredAttr>();
   }

   /// Determine the kind of initializer this is.
   CtorInitializerKind getInitKind() const;

   /// Whether this is a designated initializer.
   bool isDesignatedInit() const {
      return getInitKind() == CtorInitializerKind::Designated;
   }

   /// Whether this is a convenience initializer.
   bool isConvenienceInit() const {
      return getInitKind() == CtorInitializerKind::Convenience ||
             getInitKind() == CtorInitializerKind::ConvenienceFactory;
   }

   /// Whether this is a factory initializer.
   bool isFactoryInit() const {
      switch (getInitKind()) {
         case CtorInitializerKind::Designated:
         case CtorInitializerKind::Convenience:
            return false;

         case CtorInitializerKind::Factory:
         case CtorInitializerKind::ConvenienceFactory:
            return true;
      }
      llvm_unreachable("bad CtorInitializerKind");
   }

   /// Determine whether this initializer is inheritable.
   bool isInheritable() const {
      switch (getInitKind()) {
         case CtorInitializerKind::Designated:
         case CtorInitializerKind::Factory:
            return false;

         case CtorInitializerKind::Convenience:
         case CtorInitializerKind::ConvenienceFactory:
            return true;
      }
      llvm_unreachable("bad CtorInitializerKind");
   }

   /// Determine if this is a failable initializer.
   bool isFailable() const {
      return Bits.ConstructorDecl.Failable;
   }

   /// Retrieve the location of the '!' or '?' in a failable initializer.
   SourceLoc getFailabilityLoc() const { return FailabilityLoc; }

   /// Whether the implementation of this method is a stub that traps at runtime.
   bool hasStubImplementation() const {
      return Bits.ConstructorDecl.HasStubImplementation;
   }

   /// Set whether the implementation of this method is a stub that
   /// traps at runtime.
   void setStubImplementation(bool stub) {
      Bits.ConstructorDecl.HasStubImplementation = stub;
   }

   ConstructorDecl *getOverriddenDecl() const {
      return cast_or_null<ConstructorDecl>(
         AbstractFunctionDecl::getOverriddenDecl());
   }

   /// Determine whether this initializer falls into the special case for
   /// Objective-C initializers with selectors longer than "init", e.g.,
   /// \c initForMemory.
   ///
   /// In such cases, one can write the Swift initializer
   /// with a single parameter of type '()', e.g,
   ///
   /// \code
   /// @objc init(forMemory: ())
   /// \endcode
   bool isObjCZeroParameterWithLongSelector() const;

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Constructor;
   }
   static bool classof(const AbstractFunctionDecl *D) {
      return classof(static_cast<const Decl*>(D));
   }
   static bool classof(const DeclContext *DC) {
      if (auto D = DC->getAsDecl())
         return classof(D);
      return false;
   }
};

/// DestructorDecl - Declares a destructor for a type.  For example:
///
/// \code
/// struct X {
///   var fd : Int
///   deinit {
///      close(fd)
///   }
/// }
/// \endcode
class DestructorDecl : public AbstractFunctionDecl {
   ParamDecl *SelfDecl;

public:
   DestructorDecl(SourceLoc DestructorLoc, DeclContext *Parent);

   ParamDecl **getImplicitSelfDeclStorage() { return &SelfDecl; }

   SourceLoc getDestructorLoc() const { return getNameLoc(); }
   SourceLoc getStartLoc() const { return getDestructorLoc(); }
   SourceRange getSourceRange() const;

   /// Retrieve the Objective-C selector for destructors.
//   ObjCSelector getObjCSelector() const;

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Destructor;
   }
   static bool classof(const AbstractFunctionDecl *D) {
      return classof(static_cast<const Decl*>(D));
   }
   static bool classof(const DeclContext *DC) {
      if (auto D = DC->getAsDecl())
         return classof(D);
      return false;
   }
};

/// Declares a precedence group.  For example:
///
/// \code
/// precedencegroup MultiplicativePrecedence {
///   associativity: right
///   higherThan: AdditivePrecedence
/// }
/// \endcode
class PrecedenceGroupDecl : public Decl {
public:
   struct Relation {
      SourceLoc NameLoc;
      Identifier Name;
      PrecedenceGroupDecl *Group;
   };

private:
   SourceLoc PrecedenceGroupLoc, NameLoc, LBraceLoc, RBraceLoc;
   SourceLoc AssociativityKeywordLoc, AssociativityValueLoc;
   SourceLoc AssignmentKeywordLoc, AssignmentValueLoc;
   SourceLoc HigherThanLoc, LowerThanLoc;
   Identifier Name;
   unsigned NumHigherThan, NumLowerThan;
   // Tail-allocated array of Relations

   Relation *getHigherThanBuffer() {
      return reinterpret_cast<Relation*>(this + 1);
   }
   const Relation *getHigherThanBuffer() const {
      return reinterpret_cast<const Relation*>(this + 1);
   }
   Relation *getLowerThanBuffer() {
      return getHigherThanBuffer() + NumHigherThan;
   }
   const Relation *getLowerThanBuffer() const {
      return getHigherThanBuffer() + NumHigherThan;
   }

   PrecedenceGroupDecl(DeclContext *DC,
                       SourceLoc precedenceGroupLoc,
                       SourceLoc nameLoc, Identifier name,
                       SourceLoc lbraceLoc,
                       SourceLoc associativityKeywordLoc,
                       SourceLoc associativityValueLoc,
                       Associativity associativity,
                       SourceLoc assignmentKeywordLoc,
                       SourceLoc assignmentValueLoc,
                       bool isAssignment,
                       SourceLoc higherThanLoc, ArrayRef<Relation> higherThan,
                       SourceLoc lowerThanLoc, ArrayRef<Relation> lowerThan,
                       SourceLoc rbraceLoc);
   friend class Decl;
   SourceLoc getLocFromSource() const { return NameLoc; }
public:
   static PrecedenceGroupDecl *create(DeclContext *dc,
                                      SourceLoc precedenceGroupLoc,
                                      SourceLoc nameLoc,
                                      Identifier name,
                                      SourceLoc lbraceLoc,
                                      SourceLoc associativityKeywordLoc,
                                      SourceLoc associativityValueLoc,
                                      Associativity associativity,
                                      SourceLoc assignmentKeywordLoc,
                                      SourceLoc assignmentValueLoc,
                                      bool isAssignment,
                                      SourceLoc higherThanLoc,
                                      ArrayRef<Relation> higherThan,
                                      SourceLoc lowerThanLoc,
                                      ArrayRef<Relation> lowerThan,
                                      SourceLoc rbraceLoc);


   SourceRange getSourceRange() const {
      return { PrecedenceGroupLoc, RBraceLoc };
   }

   /// Return the location of 'precedencegroup' in:
   ///   precedencegroup MultiplicativePrecedence { ... }
   SourceLoc getPrecedenceGroupLoc() const { return PrecedenceGroupLoc; }

   /// Return the location of 'MultiplicativePrecedence' in:
   ///   precedencegroup MultiplicativePrecedence { ... }
   SourceLoc getNameLoc() const {
      return NameLoc;
   }

   Identifier getName() const {
      return Name;
   }

   SourceLoc getLBraceLoc() const { return LBraceLoc; }
   SourceLoc getRBraceLoc() const { return RBraceLoc; }

   bool isAssociativityImplicit() const {
      return AssociativityKeywordLoc.isInvalid();
   }

   /// Return the location of 'associativity' in:
   ///   associativity: left
   SourceLoc getAssociativityKeywordLoc() const {
      return AssociativityKeywordLoc;
   }

   /// Return the location of 'right' in:
   ///   associativity: right
   SourceLoc getAssociativityValueLoc() const {
      return AssociativityValueLoc;
   }

   Associativity getAssociativity() const {
      return Associativity(Bits.PrecedenceGroupDecl.Associativity);
   }
   bool isLeftAssociative() const {
      return getAssociativity() == Associativity::Left;
   }
   bool isRightAssociative() const {
      return getAssociativity() == Associativity::Right;
   }
   bool isNonAssociative() const {
      return getAssociativity() == Associativity::None;
   }

   bool isAssignmentImplicit() const {
      return AssignmentKeywordLoc.isInvalid();
   }

   /// Return the location of 'assignment' in:
   ///   assignment: true
   SourceLoc getAssignmentKeywordLoc() const {
      return AssignmentKeywordLoc;
   }

   /// Return the location of 'assignment' in:
   ///   assignment: true
   SourceLoc getAssignmentValueLoc() const {
      return AssignmentValueLoc;
   }

   bool isAssignment() const {
      return Bits.PrecedenceGroupDecl.IsAssignment;
   }

   bool isHigherThanImplicit() const {
      return HigherThanLoc.isInvalid();
   }

   /// Return the location of 'higherThan' in:
   ///   higherThan: AdditivePrecedence
   SourceLoc getHigherThanLoc() const {
      return HigherThanLoc;
   }

   ArrayRef<Relation> getHigherThan() const {
      return { getHigherThanBuffer(), NumHigherThan };
   }
   MutableArrayRef<Relation> getMutableHigherThan() {
      return { getHigherThanBuffer(), NumHigherThan };
   }

   bool isLowerThanImplicit() const {
      return LowerThanLoc.isInvalid();
   }

   /// Return the location of 'lowerThan' in:
   ///   lowerThan: MultiplicativePrecedence
   SourceLoc getLowerThanLoc() const {
      return LowerThanLoc;
   }

   ArrayRef<Relation> getLowerThan() const {
      return { getLowerThanBuffer(), NumLowerThan };
   }
   MutableArrayRef<Relation> getMutableLowerThan() {
      return { getLowerThanBuffer(), NumLowerThan };
   }

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::PrecedenceGroup;
   }
};

/// Abstract base class of operator declarations.
class OperatorDecl : public Decl {
   SourceLoc OperatorLoc, NameLoc;

   Identifier name;

   ArrayRef<Identifier> Identifiers;
   ArrayRef<SourceLoc> IdentifierLocs;
   ArrayRef<NominalTypeDecl *> DesignatedNominalTypes;
   SourceLoc getLocFromSource() const { return NameLoc; }
   friend class Decl;
public:
   OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc,
                Identifier Name, SourceLoc NameLoc,
                ArrayRef<Identifier> Identifiers,
                ArrayRef<SourceLoc> IdentifierLocs)
      : Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name),
        Identifiers(Identifiers), IdentifierLocs(IdentifierLocs) {}

   OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc,
                Identifier Name, SourceLoc NameLoc,
                ArrayRef<NominalTypeDecl *> DesignatedNominalTypes)
      : Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name),
        DesignatedNominalTypes(DesignatedNominalTypes) {}


   SourceLoc getOperatorLoc() const { return OperatorLoc; }
   SourceLoc getNameLoc() const { return NameLoc; }
   Identifier getName() const { return name; }

   ArrayRef<Identifier> getIdentifiers() const {
      return Identifiers;
   }

   ArrayRef<SourceLoc> getIdentifierLocs() const {
      return IdentifierLocs;
   }

   ArrayRef<NominalTypeDecl *> getDesignatedNominalTypes() const {
      return DesignatedNominalTypes;
   }

   void setDesignatedNominalTypes(ArrayRef<NominalTypeDecl *> nominalTypes) {
      DesignatedNominalTypes = nominalTypes;
   }

   static bool classof(const Decl *D) {
      // Workaround: http://llvm.org/PR35906
      if (DeclKind::Last_Decl == DeclKind::Last_OperatorDecl)
         return D->getKind() >= DeclKind::First_OperatorDecl;
      return D->getKind() >= DeclKind::First_OperatorDecl
             && D->getKind() <= DeclKind::Last_OperatorDecl;
   }
};

/// Declares the behavior of an infix operator. For example:
///
/// \code
/// infix operator /+/ : AdditionPrecedence, Numeric
/// \endcode
class InfixOperatorDecl : public OperatorDecl {
   SourceLoc ColonLoc;

public:
   InfixOperatorDecl(DeclContext *DC, SourceLoc operatorLoc, Identifier name,
                     SourceLoc nameLoc, SourceLoc colonLoc,
                     ArrayRef<Identifier> identifiers,
                     ArrayRef<SourceLoc> identifierLocs)
      : OperatorDecl(DeclKind::InfixOperator, DC, operatorLoc, name, nameLoc,
                     identifiers, identifierLocs),
        ColonLoc(colonLoc) {}

   SourceLoc getEndLoc() const {
      auto identifierLocs = getIdentifierLocs();
      if (identifierLocs.empty())
         return getNameLoc();

      return identifierLocs.back();
   }

   SourceRange getSourceRange() const {
      return { getOperatorLoc(), getEndLoc() };
   }

   SourceLoc getColonLoc() const { return ColonLoc; }

   PrecedenceGroupDecl *getPrecedenceGroup() const;

   /// True if this decl's attributes conflict with those declared by another
   /// operator.
   bool conflictsWith(InfixOperatorDecl *other) {
      return getPrecedenceGroup() != other->getPrecedenceGroup();
   }

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::InfixOperator;
   }
};

/// Declares the behavior of a prefix operator. For example:
///
/// \code
/// prefix operator /+/ {}
/// \endcode
class PrefixOperatorDecl : public OperatorDecl {
public:
   PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
                      SourceLoc NameLoc,
                      ArrayRef<Identifier> Identifiers,
                      ArrayRef<SourceLoc> IdentifierLocs)
      : OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc,
                     Identifiers, IdentifierLocs) {}

   PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
                      SourceLoc NameLoc,
                      ArrayRef<NominalTypeDecl *> designatedNominalTypes)
      : OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc,
                     designatedNominalTypes) {}

   SourceRange getSourceRange() const {
      return { getOperatorLoc(), getNameLoc() };
   }

   /// True if this decl's attributes conflict with those declared by another
   /// PrefixOperatorDecl.
   bool conflictsWith(PrefixOperatorDecl *other) {
      return false;
   }

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::PrefixOperator;
   }
};

/// Declares the behavior of a postfix operator. For example:
///
/// \code
/// postfix operator /+/ {}
/// \endcode
class PostfixOperatorDecl : public OperatorDecl {
public:
   PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
                       SourceLoc NameLoc,
                       ArrayRef<Identifier> Identifiers,
                       ArrayRef<SourceLoc> IdentifierLocs)
      : OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc,
                     Identifiers, IdentifierLocs) {}

   PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
                       SourceLoc NameLoc,
                       ArrayRef<NominalTypeDecl *> designatedNominalTypes)
      : OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc,
                     designatedNominalTypes) {}

   SourceRange getSourceRange() const {
      return { getOperatorLoc(), getNameLoc() };
   }

   /// True if this decl's attributes conflict with those declared by another
   /// PostfixOperatorDecl.
   bool conflictsWith(PostfixOperatorDecl *other) {
      return false;
   }

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::PostfixOperator;
   }
};

/// Represents a hole where a declaration should have been.
///
/// Among other things, these are used to keep vtable layout consistent.
class MissingMemberDecl : public Decl {
   DeclName Name;

   MissingMemberDecl(DeclContext *DC, DeclName name,
                     unsigned vtableEntries,
                     unsigned fieldOffsetVectorEntries)
      : Decl(DeclKind::MissingMember, DC), Name(name) {
      Bits.MissingMemberDecl.NumberOfVTableEntries = vtableEntries;
      assert(getNumberOfVTableEntries() == vtableEntries && "not enough bits");
      Bits.MissingMemberDecl.NumberOfFieldOffsetVectorEntries =
         fieldOffsetVectorEntries;
      assert(getNumberOfFieldOffsetVectorEntries() == fieldOffsetVectorEntries
             && "not enough bits");
      setImplicit();
   }
   friend class Decl;
   SourceLoc getLocFromSource() const {
      return SourceLoc();
   }
public:
   static MissingMemberDecl *
   create(AstContext &ctx, DeclContext *DC, DeclName name,
          unsigned numVTableEntries, bool hasStorage) {
      assert((!numVTableEntries || isa<InterfaceDecl>(DC) || isa<ClassDecl>(DC)) &&
                                                           "Only classes and Interfaces have vtable/witness table entries");
      assert((!hasStorage || !isa<InterfaceDecl>(DC)) &&
                            "Interfaces cannot have missing stored properties");

      return new (ctx) MissingMemberDecl(DC, name, numVTableEntries, hasStorage);
   }

   DeclName getFullName() const {
      return Name;
   }

   unsigned getNumberOfVTableEntries() const {
      return Bits.MissingMemberDecl.NumberOfVTableEntries;
   }

   unsigned getNumberOfFieldOffsetVectorEntries() const {
      return Bits.MissingMemberDecl.NumberOfFieldOffsetVectorEntries;
   }

   SourceRange getSourceRange() const {
      return SourceRange();
   }

   static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::MissingMember;
   }
};

inline bool AbstractStorageDecl::isSettable(const DeclContext *UseDC,
                                            const DeclRefExpr *base) const {
   if (auto vd = dyn_cast<VarDecl>(this))
      return vd->isSettable(UseDC, base);

   auto sd = cast<SubscriptDecl>(this);
   return sd->supportsMutation();
}

inline void
AbstractStorageDecl::overwriteSetterAccess(AccessLevel accessLevel) {
   Accessors.setInt(accessLevel);
   if (auto setter = getAccessor(AccessorKind::Set))
      setter->overwriteAccess(accessLevel);
   if (auto modify = getAccessor(AccessorKind::Modify))
      modify->overwriteAccess(accessLevel);
   if (auto mutableAddressor = getAccessor(AccessorKind::MutableAddress))
      mutableAddressor->overwriteAccess(accessLevel);
}

/// Constructors and destructors always have a 'self' parameter,
/// which is stored in an instance member. Functions only have a
/// 'self' if they are declared inside of a nominal type or extension,
/// in which case we tail-allocate storage for it.
inline ParamDecl **AbstractFunctionDecl::getImplicitSelfDeclStorage() {
   switch (getKind()) {
      default: llvm_unreachable("Unknown AbstractFunctionDecl!");
      case DeclKind::Constructor:
         return cast<ConstructorDecl>(this)->getImplicitSelfDeclStorage();
      case DeclKind::Destructor:
         return cast<DestructorDecl>(this)->getImplicitSelfDeclStorage();
      case DeclKind::Func:
      case DeclKind::Accessor:
         return cast<FuncDecl>(this)->getImplicitSelfDeclStorage();
   }
}

inline ParamDecl **FuncDecl::getImplicitSelfDeclStorage() {
   if (!hasImplicitSelfDecl())
      return nullptr;

   if (!isa<AccessorDecl>(this)) {
      assert(getKind() == DeclKind::Func && "no new kinds of functions");
      return reinterpret_cast<ParamDecl **>(this+1);
   }
   return reinterpret_cast<ParamDecl **>(static_cast<AccessorDecl*>(this)+1);
}

inline DeclIterator &DeclIterator::operator++() {
   Current = Current->NextDecl;
   return *this;
}

inline bool AbstractFunctionDecl::hasForcedStaticDispatch() const {
   if (auto func = dyn_cast<FuncDecl>(this))
      return func->hasForcedStaticDispatch();
   return false;
}

inline bool ValueDecl::isStatic() const {
   // Currently, only storage and function decls can be static/class.
   if (auto storage = dyn_cast<AbstractStorageDecl>(this))
      return storage->isStatic();
   if (auto func = dyn_cast<FuncDecl>(this))
      return func->isStatic();
   return false;
}

inline bool ValueDecl::isImportAsMember() const {
   if (auto func = dyn_cast<AbstractFunctionDecl>(this))
      return func->isImportAsMember();
   return false;
}

inline bool ValueDecl::hasCurriedSelf() const {
   if (auto *afd = dyn_cast<AbstractFunctionDecl>(this))
      return afd->hasImplicitSelfDecl();
   if (isa<EnumElementDecl>(this))
      return true;
   return false;
}

inline bool ValueDecl::hasParameterList() const {
   if (auto *eed = dyn_cast<EnumElementDecl>(this))
      return eed->hasAssociatedValues();
   return isa<AbstractFunctionDecl>(this) || isa<SubscriptDecl>(this);
}

inline unsigned ValueDecl::getNumCurryLevels() const {
   unsigned curryLevels = 0;
   if (hasParameterList())
      curryLevels++;
   if (hasCurriedSelf())
      curryLevels++;
   return curryLevels;
}

inline bool Decl::isPotentiallyOverridable() const {
   if (isa<VarDecl>(this) ||
       isa<SubscriptDecl>(this) ||
       isa<FuncDecl>(this) ||
       isa<DestructorDecl>(this)) {
      return getDeclContext()->getSelfClassDecl();
   } else {
      return false;
   }
}

inline GenericParamKey::GenericParamKey(const GenericTypeParamDecl *d)
   : depth(d->getDepth()), index(d->getIndex()) { }

inline const GenericContext *Decl::getAsGenericContext() const {
   switch (getKind()) {
      default: return nullptr;
#define DECL(Id, Parent) // See previous line
#define GENERIC_DECL(Id, Parent) \
  case DeclKind::Id: \
    return static_cast<const Id##Decl*>(this);
#include "polarphp/ast/DeclNodesDef.h"
   }
}

inline bool DeclContext::classof(const Decl *D) {
   switch (D->getKind()) { //
      default: return false;
#define DECL(ID, PARENT) // See previous line
#define CONTEXT_DECL(ID, PARENT) \
  case DeclKind::ID: return true;
#include "polarphp/ast/DeclNodesDef.h"
   }
}

inline DeclContext *DeclContext::castDeclToDeclContext(const Decl *D) {
   // XXX -- ModuleDecl is not defined in Decl.h, but because DeclContexts
   // preface decls in memory, any DeclContext type will due.
   const DeclContext *DC = static_cast<const ExtensionDecl*>(D);
   switch (D->getKind()) {
      default: llvm_unreachable("Not a DeclContext");
#define DECL(ID, PARENT) // See previous line
#define CONTEXT_DECL(ID, PARENT) \
  case DeclKind::ID:
#include "polarphp/ast/DeclNodesDef.h"
         return const_cast<DeclContext *>(DC);
   }
}

inline EnumElementDecl *EnumDecl::getUniqueElement(bool hasValue) const {
   EnumElementDecl *result = nullptr;
   bool found = false;
   for (auto elt : getAllElements()) {
      if (elt->hasAssociatedValues() == hasValue) {
         if (found)
            return nullptr;
         found = true;
         result = elt;
      }
   }
   return result;
}

/// Retrieve the parameter list for a given declaration.
ParameterList *getParameterList(ValueDecl *source);

/// Retrieve parameter declaration from the given source at given index.
const ParamDecl *getParameterAt(const ValueDecl *source, unsigned index);

/// Display Decl subclasses.
void simple_display(llvm::raw_ostream &out, const Decl *decl);

/// Display ValueDecl subclasses.
void simple_display(llvm::raw_ostream &out, const ValueDecl *decl);

/// Display ExtensionDecls.
inline void simple_display(llvm::raw_ostream &out, const ExtensionDecl *decl) {
   simple_display(out, static_cast<const Decl *>(decl));
}

/// Display NominalTypeDecls.
inline void simple_display(llvm::raw_ostream &out,
                           const NominalTypeDecl *decl) {
   simple_display(out, static_cast<const Decl *>(decl));
}

inline void simple_display(llvm::raw_ostream &out,
                           const AssociatedTypeDecl *decl) {
   simple_display(out, static_cast<const Decl *>(decl));
}

/// Display GenericContext.
///
/// The template keeps this sorted down in the overload set relative to the
/// more concrete overloads with Decl pointers thereby breaking a potential ambiguity.
template <typename T>
inline typename std::enable_if<std::is_same<T, GenericContext>::value>::type
simple_display(llvm::raw_ostream &out, const T *GC) {
   simple_display(out, GC->getAsDecl());
}

/// Display GenericParamList.
void simple_display(llvm::raw_ostream &out, const GenericParamList *GPL);

/// Extract the source location from the given declaration.
SourceLoc extractNearestSourceLoc(const Decl *decl);

/// Extract the source location from the given declaration.
inline SourceLoc extractNearestSourceLoc(const ExtensionDecl *ext) {
   return extractNearestSourceLoc(static_cast<const Decl *>(ext));
}

/// Extract the source location from the given declaration.
inline SourceLoc extractNearestSourceLoc(const GenericTypeDecl *type) {
   return extractNearestSourceLoc(static_cast<const Decl *>(type));
}

/// Extract the source location from the given declaration.
inline SourceLoc extractNearestSourceLoc(const NominalTypeDecl *type) {
   return extractNearestSourceLoc(static_cast<const Decl *>(type));
}

/// Extract the source location from the given declaration.
inline SourceLoc extractNearestSourceLoc(const AbstractFunctionDecl *func) {
   return extractNearestSourceLoc(static_cast<const Decl *>(func));
}

} // end namespace polar

#endif
